Understanding @Bean and @Autowired Annotations in Spring Framework

1 min read

Understanding @Bean and @Autowired Annotations in Spring Framework

The Spring Framework offers powerful dependency injection features that simplify Java application development. Two commonly used annotations in Spring are @Bean and @Autowired.

In this article, we’ll explore what each annotation does, how they work together, and walk through a full working example.


What is @Bean?

The @Bean annotation tells Spring that a method will return an object that should be registered as a bean in the Spring application context. It’s typically used within a class annotated with @Configuration.

Basic Example

Let’s say we have a simple UserRepository class that provides user data.

UserRepository.java

public class UserRepository {
    public String getUser() {
        return "John Doe";
    }
}

Now, we want to define this class as a Spring-managed bean.

AppConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
}

When the Spring application starts, it will register a UserRepository bean in its context.


What is @Autowired?

The @Autowired annotation tells Spring to automatically inject a bean where it’s required. It can be used on constructors, fields, or setter methods.

This works especially well with beans defined using @Bean.

Using @Autowired with Constructor Injection

Let’s add a UserService that depends on UserRepository.

UserService.java

import org.springframework.beans.factory.annotation.Autowired;

public class UserService {

private final UserRepository userRepository;

@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}

public String getUserInfo() {
return "User Info: " + userRepository.getUser();
}
}

This constructor tells Spring to inject an instance of UserRepository into UserService.


Wiring it All Together with @Bean and @Autowired

We now define both beans in our configuration class:

Updated AppConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }

    @Bean
    public UserService userService(UserRepository userRepository) {
        return new UserService(userRepository);
    }
}

Even though we are using @Autowired in the UserService constructor, Spring will automatically inject the UserRepository bean we declared.


Running the Application

Application.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        UserService userService = context.getBean(UserService.class);
        System.out.println(userService.getUserInfo());
    }
}

Output:

pgsqlCopyEditUser Info: John Doe

Best Practices

  • Use @Bean when you need fine-grained control over bean creation.
  • Prefer constructor-based injection with @Autowired for better testability and immutability.
  • Avoid field injection if possible; it’s less flexible and harder to test.

Conclusion

Spring’s @Bean and @Autowired annotations work hand in hand to provide flexible and powerful dependency injection. With these tools, you can easily manage object creation and wiring, making your code cleaner, modular, and testable.

🤞 Never miss a story from us, get weekly updates to your inbox!

Leave a Reply

Your email address will not be published. Required fields are marked *