I'm experimenting with examples from this official Spring tutorials and there is a dependency on this code:
https://github.com/spring-guides/gs-async-method/tree/master/complete
If you look at the code on AppRunner.java
class, I have 2 questions:
When server is starting, if I put a breakpoint in this class's constructor, seems like in the constructor, the GitHubLookupService is provided by spring, using the @Service bean that was configured. BUT, there was no @Autowired annotation on the constructor, so how in the world this constructor get called with the right dependency? It was supposed to be null.
Is it an automatic assumption of Spring Boot? Does Spring see "private field + constructor argument, and it assumes it should look for an appropriate bean? Is it Spring Framework or Spring boot? Am I missing something?
As I remember, it was mendatory to provide default constructor to beans / service etc. How come this class (AppRunner) doesn't have a default constructor? How does Spring knows that it should run the constructor with the argument? Is it because it is the only constructor?
Starting with Spring 4.3, if a class, which is configured as a Spring bean, has only one constructor, the @Autowired
annotation can be omitted and Spring will use that constructor and inject all necessary dependencies.
Regarding the default constructor: You either need the default constructor, a constructor with the @Autowired
annotation when you have multiple constructors, or only one constructor in your class with or without the @Autowired
annotation.
Read the @Autowired
chapter from the official Spring documentation for more information.
Think of it this way... Suppose you have the following component:
@Component
public class FooService {
public FooService(Bar bar) { /*whatever*/ }
}
When Spring is scanning this class, it wants to know how it should go about constructing an instance. It's using reflection so it can get a list of all of the constructors at runtime.
In this case, it is completely unambiguous how Spring must construct this instance. There's only one constructor so there is no decision to be made, and no ambiguity at all.
If you add @Autowired
here, you are not narrowing anything down, and you are not giving Spring any extra information to help make its decision - its decision is already made because there is only one candidate.
And so, as a convenience, the Spring team decided @Autowired
should be optional. Since its not helping the Spring framework to make a decision, its presence is just noise.
If your component has multiple constructors then you can use @Autowired
on one of them to tell Spring "use this one, not that one".
Success story sharing
PropertySource
. Could that be the cause? Is there a way to avoid that autowiring?