I used to be a huge fan of field injection.
But one day I started to question myself. Could it be possible that I have been mistaken?
Let’s find out what happened.
Can It Be Too Simple?
I was, of course, aware of the fact that field injection versus constructor injection versus setter injection is a somewhat hot topic.
I was also aware of pros and cons of each approach. The problem was that those arguments did not resonate to me on a deeper level.
The benefits of each approach seemed clear and a bit too academic at the same time. Maybe I was not ready to really understand them yet.
To make matters worse, I really thought that I could get the good stuff of field injection and all the bad stuff would magically disappear.
I agree. I was an arrogant ass.
Nevertheless, I continued using field injection. Why? Let’s find out.
I have created a service class which uses field injection. Its source code looks as follows:
1@Service
2public class PersonServiceImpl implements PersonService {
3
4 @Autowired
5 Private PersonRepository repository;
6
7}
Now, the reason why I preferred field injection over constructor injection was that it looks a lot simpler than constructor injection. The same service class which uses constructor injection looks as follows:
1@Service
2public class PersonServiceImpl implements PersonService {
3
4 private final PersonRepository repository;
5
6 @Autowired
7 public PersonServiceImpl(PersonRepository repository) {
8 this.repository = repository;
9 }
10}
It does not look very clean or elegant. Right?
Wait, it gets even better. What if I add some dependencies to my service class?
If I use field injection, my service class will still look clean:
1@Service
2public class PersonServiceImpl implements PersonService {
3
4 @Autowired
5 private PersonRepository repository;
6
7 @Autowired
8 Private ServiceA serviceA;
9
10 @Autowired
11 Private ServiceB serviceB;
12}
On the other hand, if I use constructor injection, the source code of my service class looks as follows:
1@Service
2public class PersonServiceImpl implements PersonService {
3
4 private final PersonRepository repository;
5
6 private final ServiceA serviceA;
7
8 private final ServiceB serviceB;
9
10 @Autowired
11 public PersonServiceImpl(PersonRepository repository, ServiceA serviceA, ServiceB serviceB) {
12 this.repository = repository;
13 this.serviceA = serviceA;
14 this.serviceB = serviceB;
15 }
16}
Pretty awful. Right?
My biggest problem with the constructor injection was that the constructors become very messy if my class has many dependencies.
Then I read this tweet by Oliver Gierke (Read the whole discussion):
Field injections is evil… hides dependencies, instead of making them explicit.
I started thinking about this tweet and and something clicked inside me. I understood that because it was so easy to add new dependencies to my classes in a “clean and elegant” way, I skipped a vital step.
It Is a Sign
When I used field injection and I needed to add a new dependency to my class, I followed these steps:
- Add a new field to the class and annotate it with the @Autowired annotation.
- Write the code which uses the added dependency.
This approach seemed clean and elegant but sadly I had misunderstood one very important thing. I thought that constructor injection makes constructors look messy and ugly. That was a huge mistake.
A messy constructor is a sign. It warns me that my class is becoming a monolith which is a jack of all trades and a master of none. In other words, a messy constructor is actually a good thing. If I feel that the constructor of a class is too messy, I know that it is time to do something about it.
I know that field injection and constructor injection have other differences as well. However, for me, my hatred of messy constructors is the most important one because it guided me to study and understand the other differences (the one’s that matter).
I hope that it will do the same for you.
Differences that Matter
I am not going to write about the differences of field injection, setter injection, and constructor injection. Instead, I will give you links to blog posts which I have found interesting and useful.
These blog posts are:
- Repeat After Me: Setter Injection is a Symptom of Design Problems. This blog post has a quite provocative title but it does a good job of pointing out the problems of setter injection.
- The One Correct Way to do Dependency Injection. This is another blog post by Jens Schauder and “surprisingly”, it also advocates constructor injection. The best part of this blog post are its comments. I recommend that you check out Oliver Gierke’s comment since it has some great insights in it.
- I was wrong: Constructor vs setter injection. This is a blog post by Steve Schols and it describes why setter injection should be preferred over constructor injection.
- Setter injection versus constructor injection and the use of @Required. This (rather old) blog post has some really interesting stuff in it. One such thing is that it describes the difference between application code and framework code and talks about how this effects to the selection of the used dependency injection method.
- Setter injection sucks. This blog post describes why setter injection should be avoided at all costs. The reason why I added it here is that the author had the same first thoughts about constructor injection than I did.
- This dependency injection madness must end! This a blog post written by Johannes Brodwall. It talks about the problems of dependency injection. Remember to read the comments of this post. If you are interested of getting something to think about, I recommend that you start reading his blog. He has a lot of good stuff in it.
Did I miss something?