The reasons why field injection is frowned upon are as follows: You cannot create immutable objects, as you can with constructor injection. Your classes have tight coupling with your DI container and cannot be used outside of it. Your classes cannot be instantiated (for example in unit tests) without reflection.
Immutable object shouldn't be possible to modify after it's constructed. Spring injects autowired private field after the object has been constructed. It's contradicting the immutability principle, so immutability is therefore broken.
Field injection is mainly used to inject variables into Android framework types that the system instantiates and on which we can't do constructor injection, like activities, BroadcastReceivers and fragments.
The Field Injection is used to inject the fields, variables, or properties of the beans. It is not available in autowiring using XML- based configuration. It is a new feature of Spring annotation-based configuration. The field injection is easy to use in comparison to constructor and setter injection.
Injection types
There are three options for how dependencies can be injected into a bean:
You are using option 3. That is what is happening when you use @Autowired
directly on your field.
Injection guidelines
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
Field injection drawbacks
The reasons why field injection is frowned upon are as follows:
Conclusion
Depending on your needs, you should primarily use constructor injection or some mix of constructor and setter injection. Field injection has many drawbacks and should be avoided. The only advantage of field injection is that it is more convenient to write, which does not outweigh all the cons.
Further reading
I wrote a blog article about why field injection is usually not recommended: Field Dependency Injection Considered Harmful.
This is one of the never-ending discussions in software development, but major influencers in the industry are getting more opinionated about the topic and started to suggest constructor injection as the better option.
Constructor injection
Pros:
Cons:
Basically, the field injection is the opposite.
Matter of taste. It is your decision.
But I can explain, why I never use constructor injection.
I don't want to implement a constructor for all my @Service
, @Repository
and @Controller
beans. I mean, there are about 40-50 beans or more. Every time if I add a new field I would have to extend the constructor. No. I don't want it and I don't have to.
What if your Bean (Service or Controller) requires a lot of other beans to be injected? A constructor with 4+ parameters is very ugly.
If I'm using CDI, constructor does not concern me.
EDIT #1: Vojtech Ruzicka said:
class has too many dependencies and is probably violating single responsibility principle and should be refactored
Yes. Theory and reality.
Here is en example: DashboardController
mapped to single path *:8080/dashboard
.
My DashboardController
collects a lot of informations from other services to display them in a dashboard / system overview page. I need this single controller. So I have to secure only this one path (basic auth or user role filter).
EDIT #2: Since everyone is focused on the 8 parameters in the constructor... This was a real-world example - an customers legacy code. I've changed that. The same argumentation applies to me for 4+ parameters.
It's all about code injection, not instance construction.
One more comment - Vojtech Ruzicka stated that Spring injects beans in such three ways (the answer with the biggest numbers of points) :
This answer is WRONG - because FOR EVERY KIND OF INJECTION SPRING USES REFLECTION! Use IDE, set breakpoint on setter / constructor, and check.
This can be a matter of taste but it can also be a matter of a CASE. @dieter provided an excellent case when field injection is better. If You're using field injection in integration tests that are setting up Spring context - the argument with testability of the class is also invalid - unless You want to write later on tests to Your integration tests ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With