Well, this seems a polemic discussion. The first thing that needs to be addressed is that Field injection is different from Setter injection. I already work with some people that thinks Field is equal Setter injection.
So, to be clear:
Field injection:
@Autowired
private SomeService someService;
Setter injection:
@Autowired
public void setSomeService(SomeService someService) {
this.someService = someService;
}
But, for me, they share some of the concerns. And, my favorite, the constructor injection:
@AutoWired
public MyService(SomeService someService) {
this.someService = someService;
}
I have the follow reasons to believe that the constructor injection is better than setter/field injection. I will quote some Spring links about this subject:
- Prevent circular dependencies: Spring is able to detect circular dependencies between the Beans, as @Tomasz explained. See also the Spring Team saying that.
- Dependencies of the class are obvious: The dependencies of the class are obvious in the constructor but hided with field/setter injection. I feel my classes like a "black box" with field/setter injection. And there is (by my experience) a tendency to developers not bother about the class with many dependencies, that is obvious when you try to mock the class using constructor injection (see the next item). A problem that bothers the developers is most likely to be resolved. Also, a class with too many dependencies probably violate the Single Responsibility Principle (SRP).
- Easy and reliable to mock: compared to Field injection, it's easier to mock in a unit test, because you don't need any context mock or reflection technic to reach the declared private Bean inside the class and you will not be fooled by it. You just instantiate the class and pass the mocked beans. Simple to understand and easy.
- Code quality tools can help you: Tools like Sonar can warn you about the class getting too complex, because a class with a lot of parameters is probably a too complex class and need some refactor.
- Better and independent code: With less
@AutoWiredspread among your code, your code is less dependent of the framework. I know that the possibility to simple change the DI framework in a project not justify that (who does that, right?). But this shows, for me, a better code (I learned this in a hard way with EJB and lookups). And with Spring you can even remove the@AutoWiredannotation using constructor injection. - More annotations is not always the right answer: For some reasons, I really try to use annotations only when they are really useful.
If you are looking for more information, I recommend this old (but still relevant) article from Spring Blog telling us why they use so much setter injection and the recommendation to use constructor injection:
setter injection is used a lot more often than you would expect, is the fact that frameworks like Spring in general, are much more suited to be configured by setter injection than by constructor injection
And this note about why they believe that constructor is more suitable for application code:
I think constructor injection is much more usable for application code than it is for framework code. In application code, you inherently have a lesser need for optional values that you need to configure
Final thoughts
If your are not really sure about the advantage of constructor, maybe the idea to mix setter (not field) with constructor injection is a option, as explained by the Spring team:
Since you can mix both, Constructor- and Setter-based DI, it is a good rule of thumb to use constructor arguments for mandatory dependencies and setters for optional dependencies
But remember the field injection is, probably, the one to be avoided among the three.