Why can\'t I use @Autowired
in this case?
@SpringBootApplication
public class Application {
@Autowired
BookingService bookingService;
great answer by @DaveyDaveDave In the example instead of
@Bean
BookingService bookingService() {
return new BookingService();
}
You can use @Service annotation on BookingService class
Whatever class you have instantiated using @Autowire, you can instantiate it inside a class with @Configuration annotation using @Bean on the method.
Both @Autowire and @Bean are ways to initialize instances of a Class.
The difference is if you use @Bean to instantiate a class, you have more control over the initialization. For example if you are instantiating a Resilience4J Circuit breaker class, if you do it inside a method with @Bean, you have the option of setting all the config using code like this
@Bean
public CircuitBreaker fooCircuitBreaker() {
CircuitBreakerConfig.Builder builder = CircuitBreakerConfig.custom().
slidingWindowSize(xxx).
failureRateThreshold(xxx).
waitDurationInOpenState(xxx)).
ignoreException(e -> {
if (e instanceof HttpStatusCodeException) {
HttpStatusCodeException httpStatusCodeException = (HttpStatusCodeException) e;
if (httpStatusCodeException.getStatusCode().is4xxClientError()) {
return true;
}
}
return false;
});
circuitBreakerRegistry.addConfiguration(xxx, builder.build());
return circuitBreakerRegistry.circuitBreaker(xxx, xxx);
}
In a case like this, using @Bean is obviously a better way.
@Bean is just for the metadata definition to create the bean(equivalent to tag). @Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).
@Bean
BookingService bookingService() {
return new BookingService();
}
Annotating @Bean
only registers the service as a bean(kind of an Object) in spring application context. In simple words, it is just registration and nothing else.
@Autowired
BookingService bookingService;
Annotating a variable with @Autowired
injects a BookingService
bean(i.e Object) from Spring Application Context.
(i.e) The registered bean with @Bean
annotation will be injected to the variable annotated with @Autowired
.
Hope this clears your doubt!
@Bean
and @Autowired
do two very different things. The other answers here explain in a little more detail, but at a simpler level:
@Bean
tells Spring 'here is an instance of this class, please keep hold of it and give it back to me when I ask'.
@Autowired
says 'please give me an instance of this class, for example, one that I created with an @Bean
annotation earlier'.
Does that make sense? In your first example, you're asking Spring to give you an instance of BookingService
, but you're never creating one, so Spring has nothing to give you. In your second example, you're creating a new instance of BookingService
, telling Spring about it, and then, in the main()
method, asking for it back.
If you wanted, you could remove the two additional lines from the second main()
method, and combine your two examples as below:
@SpringBootApplication
public class Application {
@Autowired
BookingService bookingService;
@Bean
BookingService bookingService() {
return new BookingService();
}
public static void main(String[] args) {
bookingService.book("Alice", "Bob", "Carol");
}
}
In this case, the @Bean
annotation gives Spring the BookingService
, and the @Autowired
makes use of it.
This would be a slightly pointless example, as you're using it all in the same class, but it becomes useful if you have the @Bean
defined in one class, and the @Autowired
in a different one.
Here's good article about @Autowired annotation: http://www.baeldung.com/spring-autowire
The @Autowired annotation can instantiate your injectables by defining @ComponentScan("namespace.with.your.components.for.inject") on config class
@Configuration
@ComponentScan("com.baeldung.autowire.sample")
public class AppConfig {}
All components must be marked by @Component annotation. It replaces the @Bean annotation.