Learn to write tests which are easy to read and write: get started with Spock Framework.

Why I Changed My Mind About Field Injection?

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:

@Service
public class PersonServiceImpl implements PersonService {

	@Autowired
	Private PersonRepository repository;

}

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:

@Service
public class PersonServiceImpl implements PersonService {

	private final PersonRepository repository;

	@Autowired
	public PersonServiceImpl(PersonRepository repository) {
		this.repository = repository;
	}
}

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:

@Service
public class PersonServiceImpl implements PersonService {

	@Autowired
	private PersonRepository repository;

	@Autowired 
	Private ServiceA serviceA;

	@Autowired
	Private ServiceB serviceB;
}

On the other hand, if I use constructor injection, the source code of my service class looks as follows:

@Service
public class PersonServiceImpl implements PersonService {

	private final PersonRepository repository;

	private final ServiceA serviceA;

	private final ServiceB serviceB;

	@Autowired
	public PersonServiceImpl(PersonRepository repository, ServiceA serviceA, ServiceB serviceB) {
		this.repository = repository;
		this.serviceA = serviceA;
		this.serviceB = serviceB;
	}
}

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:

  1. Add a new field to the class and annotate it with the @Autowired annotation.
  2. 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:

Did I miss something?

If you are using Spring Framework, and you want to cure the disease called field injection, you should take a look at Ninjector.

About the Author

Petri Kainulainen is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

About Petri Kainulainen →

36 comments… add one
  • I also agree that a “messy” constructor encourages us to rethink design and can be used as a valid argument for using constructor injection.

    Still, I believe the main reason really is about communicating publicly your dependencies. Also, we must be religious to use the @Nullable annotation, as it publicly informs whether a dependency is required or not (although it makes your ctor even messy).

    A single complete constructor is a good way of exposing your class publicly.

    Good research.

    Reply
    • Daniel,

      Your second point (exposing your dependencies) is actually the most important reason of using constructor injection. The problem was that I couldn’t see the value of that until I realized that messy constructors means that my code has too many dependencies. To be honest, I have no idea how I could think otherwise.

      By the way, thanks for the tip concerning the @Nullable annotation. I will start using it right away.

      Reply
  • Petri/Daniel,

    How about Abstract Spring Bean, which has say 10 sub-classes? If we go with Constructor injection, any addition of dependency will require all 10 sub-classes to be changed.

    Reply
    • Hi Swat,

      I would use constructor injection for mandatory dependencies and setter injection for optional dependencies. This way you are not hiding the dependencies but you are not cluttering the constructors either.

      Also, you might want to take a look at this blog post.

      Reply
  • If I read correctly, Constructor injection is better because.. When you have too many dependancies it gets really messy so you know you are doing something bad. I personally don’t believe that this is a universally applicable argument. If you implemented a policy of putting a 5 line comment above each field, you’d get the same level of drudgery and bloat when those dependancies started accumulating, yet noone is advocating that approach :P

    At a high level, making things harder so I can quickly spot when it’s becoming ‘too hard’, doesn’t personally help. I know roughly how many dependancies are ‘too many’, and whether they are expressed in 3 lines or 30, it doesn’t change the number of them. They’re not hidden.. They’re right at the top of my code file.

    My 2 cents anyway :) fwiw, I’ve used constructor injection exclusively, and am just starting out with alternatives due to the refactor pain involved. We’ll see if I run screaming back to constructor injection ;)

    Reply
    • Hi Mike,

      actually I meant that the messy constructor “syndrome” isn’t caused by constructor injection. It is just something that happens if the class has too many dependencies.

      If I would have to argue why constructor injection is better than field injection, I would probably use these “universal” arguments:

      • It makes dependencies explicit.
      • It prevents circular dependencies.
      • It ensures that dependencies can be declared final.

      Are these good arguments? At the moment I think so. However, I also think that you shouldn’t be too fanatic about this. If using field injection makes sense, you should definitely use it as long as you know why it makes sense.

      Reply
  • What about considering the @Required annotation, Placing the important dependencies with @Required at the top in a visible place will mean that a components remain readable and can still benefit from code reducing libraries such as lombok.

    Reply
    • In my opinion the @Required annotation doesn’t eliminate the downsides of field injection. On the other hand, if you want to use field injection and it is working for you, you should definitely continue using it.

      By the way, you can use Project Lombok even if you use constructor injection. Olivier Gierke has written a blog post titled: Why field injection is evil, and he explains how you can combine the benefits of constructor injection and Project Lombok.

      Reply
      • I’m beginning to see why field injection makes classes surreptitiously explode with functionality. and thanks for pointing out that lombok/constructor blog post :)

        Reply
        • Hi Jared,

          I think that using field injection doesn’t automatically mean that your classes will end up being bloated monsters with too many dependencies. You can definitely write clean and modular code if you use field injection, but like I said, it is so damn easy to add “just one more” field to a class.

          Reply
  • Thanks, this post shows a new point to me.

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you.

      Reply
  • Great and inspiring article. Great research!

    One thing I would like to mention about constructor dependency injection and Spring is that when you would like to inject AOP proxied beans without an interface via constructor in Spring prior to 4.0 you will get an exception:

    
    @Component
    public class Collaborator { // does not implement interface
        public String collaborate() {
            return "Collaborating";
        }
    }
    
    

    And the wiring:

    
    @Service
    public class SomeService {
    
        private final Collaborator collaborator;
    
        @Autowired
        public SomeService(Collaborator collaborator) {
            this.collaborator = collaborator;
        }
    
        public String businessMethod() {
            return collaborator.collaborate();
        }
    }
    
    

    The above will only work if Collaborator is not CGLIB-proxied bean.

    In your examples you have interface for every dependency, so this is not an issue. In my opinion, not every class or collaborator you use in code must implement interfaces. In such a case you may run into problems while using Spring 3.

    Fortunately starting with Spring 4 this is no more an issue as CGLIB-based proxy classes no longer require a default constructor.

    I blogged about it: http://blog.codeleak.pl/2014/07/spring-4-cglib-based-proxy-classes-with-no-default-ctor.html

    Once again, thanks for this post!

    Reply
    • Thank you for an interesting comment!

      I agree that the behavior of older Spring versions (< 4.x) is very "painful" because often you have to add the default constructor because of the reasons you mentioned. Luckily this is no longer necessary if you use Spring 4.By the way, you mentioned that you don't think that every class or collaborator must implement an interface. I agree with you. Have you any specific "rules" which you use when you decide that this class doesn't have to implement an interface?

      Reply
      • Good question about the rules. I would say – if you know there will be only one implementation, introducing interface may be an overhead. This works fine for some helper classes, e.g. @Controller helpers are just good candidates for having no interface.

        Reply
  • Hi,

    You’re not arrogant just because you question something. You don’t strike me as arrogant at all – in fact I encourage you to question things more.

    One key capability of dependency injection that you’re missing here is the ability to resolve the sequence that objects are constructed. That’s the problem with constructor injection. The dependencies being injected have to have been constructed before they are injected. Field or ‘setter’ injection allows Spring (or any other framework) to construct the dependencies and inject them as they become available. Spring even has the InitializingBean.afterPropertiesSet() method that’s designed to allow objects to perform some function after all dependencies have been satisfied.

    Constructor injection leads to deadlock when attempting to inject circular dependencies. I.e. A->B, B->C and C->A. Then you have to start using factory or ‘provider’ classes, and you still can’t predict when these things are going to be available and have even worse dependency chains to contend with.

    Field or Setter Injection is far cleaner.

    Reply
    • Thank you for an interesting comment!

      One key capability of dependency injection that you’re missing here is the ability to resolve the sequence that objects are constructed. That’s the problem with constructor injection. The dependencies being injected have to have been constructed before they are injected.

      I think that this is a good thing because it forces me to divide my code into modules that have a clear public interface. Typically this is a problem if you have circular dependencies in your code, and I think circular dependencies are an anti-pattern.

      Constructor injection leads to deadlock when attempting to inject circular dependencies. I.e. A->B, B->C and C->A. Then you have to start using factory or ‘provider’ classes, and you still can’t predict when these things are going to be available and have even worse dependency chains to contend with.

      I think that this is a good thing because it forces me to fix the problem found from my design (circular dependencies).

      Field or Setter Injection is far cleaner.

      Well, I still prefer constructor injection for mandatory dependencies and setter injection for optional dependencies, but I understand that other people might have different preferences. Also, it is true that if you want to support circular dependencies, you cannot use constructor injection.

      Reply
  • Why I use constructor injection from beginning, if you are in my case, developing api project and implementation project and want to restrict the implementation, while you are not using spring in api project, the only way is to use constructor injection, it is like forcing implementation to do things in the way that api plan.

    Reply
  • Thanks for this useful summary.

    I guess there is no harm in using field injection in test classes, right?

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you.

      I guess there is no harm in using field injection in test classes, right?

      You are right. I use field injection in my integration test classes because using constructor injection in test classes doesn’t really make any sense to me.

      Reply
  • I fully agree that constructor injection is the best way to do DI.

    I do however have a problem with optional dependencies: Most people suggest to use setter injection for optional dependencies, but if I do that, I can’t make those fields final anymore. Is there a way to use constructor injection and still have optional depencies?

    Reply
  • Hi.

    As you write, it seem marvelous, but once you create the project and add this line in PersonServiceImpl.java
    @Autowired
    Private PersonRepository repository;

    Everything fails, and after day seeing this error message is difficult to continue with your explanations:
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘personServiceImpl’: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.jpa.repository.PersonRepository org.jpa.service.PersonServiceImpl.personRepository; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘personRepository’: FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: [Assertion failed] – this argument is required; it must not be null

    Reply
    • Hi David,

      Unfortunately I don’t understand your point. Could you clarify it a bit?

      Reply
  • Thanks. So what do you suggest I should use? Constructor injection or Setter Injection or Field Injection? Because I can still see many examples online(Spring controllers and Service) using field injections. If I’m not using JUnit, can I use field injection or should I change field injections to constructor injection?

    Thanks.

    Reply
    • Hi,

      So what do you suggest I should use? Constructor injection or Setter Injection or Field Injection?

      Nowadays I use constructor injection for required dependencies and setter injection for optional dependencies. However, I must admit that some of my examples might use field injection since I have some quite old examples and I just simply don’t have time to update them.

      If I’m not using JUnit, can I use field injection or should I change field injections to constructor injection?

      You can actually use field injection even if you use JUnit or some other testing library. Still, I would use the approach described above.

      Reply
  • Good article, thanks for helping me understand better dependency injection.

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you.

      Reply
  • Thanks for such an interesting post, which helps to understand the things deeper. I’m going to change my habit about field injection right now :)

    Just to mention, I’ve found your blog recently and like it a lot. Thanks for all your efforts.

    Reply
    • You are welcome. I am happy to hear that this blog post was useful to you.

      Reply

Leave a Comment