Spring @Autowire on Properties vs Constructor
Good to know
If there is only one constructor call, there is no need to include an @Autowired annotation. Then you can use something like this:
@RestController
public class NiceController {
private final DataRepository repository;
public NiceController(ChapterRepository repository) {
this.repository = repository;
}
}
... example of Spring Data Repository injection.
Please note, that since Spring 4.3 you don't even need an @Autowired on your constructor, so you can write your code in Java style rather than tying to Spring's annotations. Your snippet would look like that:
@Component
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
I will explain you in simple words:
In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like new SomeService()
), which is NOT good as you need SomeOtherService
object (as a dependency) for your SomeService
.
Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?
Option(B) is preferred approach as it does NOT allow to create SomeService
object without actually resolving the SomeOtherService
dependency.
Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:
- the dependencies are clearly identified. There is no way to forget one when testing, or instantiating the object in any other circumstance (like creating the bean instance explicitly in a config class)
- the dependencies can be final, which helps with robustness and thread-safety
- you don't need reflection to set the dependencies. InjectMocks is still usable, but not necessary. You can just create mocks by yourself and inject them by simply calling the constructor
See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.