I was wrong: Constructor vs. setter injection

Reading books or reference documentation is always good to get new ideas or to gain new insights.
While reading the Spring reference documentation, I realized I was wrong!

In one of my previous blog posts about Dependency Injection vs. Service Locator, specifically in the part “The final clash – Constructor vs. setter injection”, I said that I agreed with Martin Fowler.

Martin advocated the use of constructor injection as much as possible unless things are getting too complex. His advice is to use constructor injection to create valid objects at construction time. This advice originates from Kent Beck’s book Smalltalk Best Practice Patterns.
I myself have always used setter injection because that was the way I was taught to use Spring. But after reading Martin Fowler’s article, I agreed with having to use constructor injection more often.
In most circumstances, now I know I was wrong.

What are the problems with constructor injection?

No reconfiguration and re-injection

As the Spring reference documentation – Constructor-based or setter-based DI? states:

The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional. Setter methods also make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is a compelling use case.

Some purists favor constructor-based injection. Supplying all object dependencies means that the object is always returned to client (calling) code in a totally initialized state. The disadvantage is that the object becomes less amenable to reconfiguration and re-injection.

Use the DI that makes the most sense for a particular class. Sometimes, when dealing with third-party classes to which you do not have the source, the choice is made for you. A legacy class may not expose any setter methods, and so constructor injection is the only available DI.

So indeed, using constructor injection when no setters exist, you cannot reconfigure the constructed bean by injecting new dependencies into it.
If you want to “reconfigure” the bean, you’ll have to construct a new bean instance using the new dependencies and discard the other one.

Circular dependencies

Another problem occurs when you’re having circular dependencies.
Again, the Spring reference documentation – Circular dependencies states:

If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.

For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.

Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken/egg scenario).

While it’s not a recommended scenario, you could create a circular dependency using Spring. But not by using constructor-based injection. If you want to create a circular dependency, you’ll have to use setter-based injection.

I have an example of this, which can be downloaded through the following link: spring-setter-injection.zip
You’ll need Maven to build and run the example.

[UPDATE]
You’ll notice that the ConstructorBasedCircularDependencyTest does not fail.
Thanks to Mathew, I found a way of testing if the expected exception will occur. Instead of relying on the SpringJUnit4ClassRunner to create the ApplicationContext, I create the ApplicationContext myself inside the test method, and annotate the test method to expect the UnsatisfiedDependencyException, which wraps the BeanCurrentlyInCreationException.
[/UPDATE]

To end this post, I’ll quickly show how to use constructor-based injection and setter-based injection using Spring annotations.

Constructor-based injection:

@Component
public class A {
    private B b;

    @Autowired
    public A(B b) {
        this.b = b;
    }

    /**
     * @return the b
     */
    public B getB() {
        return b;
    }
}

Setter-based injection:

@Component
public class A {
    private B b;

    /**
     * @return the b
     */
    public B getB() {
        return b;
    }

    /**
     * @param b
     *            the b to set
     */
    @Autowired
    public void setB(B b) {
        this.b = b;
    }
}

So sometimes, when you get a new insight, you have to be able to acknowledge you were wrong about something.
I hope you all enjoyed reading this post. Feel free to post your comments below.

[UPDATE]
As I said before, a circular dependency is something that is to be avoided! But when you stumble upon one and you cannot refactor it out immediately, constructor injection is not going to work in that scenario. At least not with Spring.

But reading Petri’s post Why I Changed My Mind About Field Injection?, again gave me new insights. He does have a point and I think the same goes for setter injection.
When you do have a messy constructor or a lot of setters, it means that something is wrong with your class design and your separation of concerns. Probably, you need to refactor some behavior out of the class to a separate one.
By the way, field injection can make unit testing harder. Using constructor or setter injection, you can define the dependencies from within your unit tests and pass them to your constructor or setter.

Use constructor injection for mandatory dependencies and setter injection for the optional ones, but make sure your constructor doesn’t get messy and you don’t end up with a whole bunch of setters. If that is the case, take a look at the separation of concerns.
[/UPDATE]

About Steve Schols

I am Steve Schols, a senior Java consultant working for several clients in Belgium. I mainly blog about the Java language and relevant frameworks and technologies. All statements made here are solely my own and do not represent the opinion of my employer, colleagues or my clients.
This entry was posted in Java, Object Oriented Design, Spring and tagged , , , , , , , , , , , . Bookmark the permalink.

29 Responses to I was wrong: Constructor vs. setter injection

  1. Daniel says:

    I tend to follow Steve Freeman’s and Nat Pryce’s approach in Growing Object-Oriented Software, Guided by Tests. Dependencies are in the constructor and configuration are provided defaults, with setters to override the default. Doing this, the user of the class will always get a valid object, and can still change configuration on the fly.

    I consider the fact that you cannot create circular dependencies as an advantage, not a problem. One is forced to come up with a better design.

    • Anonymous Coward says:

      What’s a bad practice in some context may be a good practice in another. Think anemic domain model. There are countless web apps implementing this model – I mention this because it’s highly polarizing and better known than other . Is it always bad? IMO not necessarily. If you have a simple domain model, on which mostly CRUD operations on persistent records happen, with very little dependencies between objects, an anemic service model is quite convenient and economic – simple stateless services, instead of complex entities with intelligence, which need to be created and destroyed constantly. Now think of the domain model for a 3D mesh of nodes with mass connected by springs. Any action upon one node will necessarily propagate through the whole mesh. Is an anemic domain model a good idea in this context? Definitely not anymore. In this case, spreading the intelligence onto many distinct node objects, instead of keeping it in stateless services, yields a solution easier to understand and test.

      The same with circular dependencies. There are several mechanisms via which you can break such a cycle. But is it always a good idea? I don’t think so. Sometimes two or more collaborating objects of different classes, depending on each other, are a nicer solution than one large object, and breaking the circular dependencies adds code without adding value. Granted, such situations are rare, but IME they do occur sometimes. Not necessarily because of technical reasons, but because of business requirements. If there’s a circular dependency in the business rules you need to implement, it is most often not a good idea not to reflect it in implementation. You’ll need to add code to re-establish the circular dependency, and just make it less obvious, if you don’t implement it the way it is in real life.

  2. Steve Schols says:

    Hi Daniel, thanks for your comment.

    Indeed, I see where you’re going with mixing both principles. It is the best of both worlds.
    Unless ofcourse when you create circular dependencies, you’ll still have problems when using Spring.
    But circular dependencies aren’t an ideal situation nonetheless, that should be avoided, like you say in your comment.

    • Esteban says:

      Hi Steve,
      Nice article. What I would comment on “The Spring team generally advocates setter injection, because large numbers of constructor arguments can get unwieldy, especially when properties are optional” is that constructors are fine even if they have multiple arguments. However, if a class requires > 6 dependencies they you should probably check the class design. May be your class is doing to many things and you should decouple in smaller classes…

      • Steve Schols says:

        Hi Esteban

        You’re absolutely right. Sometimes I have to reflect on a topic a little bit further I guess 🙂
        Too many dependencies can be a sign of breaking the single responsibility principle.
        Of course, a Service class can have multiple services or DAO’s as a dependency, but you can never have much more than a few.

  3. Pingback: Schauderhaft » Repeat After Me: Setter Injection is a Symptom of Design Problems

  4. Daniel (not the same Daniel as the earlier poster) says:

    I think the spring recommendations solutions in this case are a tad off. The biggest advantage of constructor-based injection is that it allows for immutable objects. When the constructor-arguments become unwieldy, I typically have spring use setter-based injection *on a builder object*, and use that builder as the sole constructor argument. This allows for complex objects as well as setter-based injection, as well as immutability.

    As for circular dependencies, the goal is minimize or eliminate them. They often represent poor organizational decisions.

    • Steve Schols says:

      Hi Daniel,

      Thanks for your reply. By all your guys replies, I get to learn new insights as well.

      I didn’t look at it that way yet, to create immutable objects or to use the builder pattern to have setter injection. I’ve read something about that in some article or the reference doc itself.
      Normally, Spring only allowed basic JavaBean-style setters that return void, but nowadays Spring removed this limitation, and you can use builder-style setters as well.

      Circular dependencies do need to be avoided indeed. The example just shows that Spring prohibits you from using them. It’s not that I was saying that prohibiting circular dependencies is a bad thing 🙂

  5. Nice post. Thanks for sharing :].

    I agree with Daniel (the first comment) that in most cases constructor injection should be used for default values and setter injection for optional values.

    About your question:
    Do you, as a reader of my blog, know of a way to accomplish also expecting exceptions at initialization time and flagging them to allow the test to succeed?

    The simplest solution is to write a test class that is not run with Spring JUnit runner (ommit the @RunWith) and try to create a Spring application context yourself. Then you can add @Test(expected=…).

    • Steve Schols says:

      Damn :-), of course, you’re right.

      Instead of using the Spring JUnit runner, just make a test method and create the ApplicationContext from within that method. I did that in one of my previous examples.

      I always try to use automatic configuration, so I didn’t think of this easy solution.

      Thanks.

  6. stijnvp says:

    Steve,

    When you put the @Autowired annotation on your instance variables you don’t need neither of them.

    I agree that Spring handles setters injection better (when you’re not using Autowired annotations but using xml or javaconfig) especially when you’re doing some refactoring. BUT if I put on my OO hat, and I don’t want that my code depends on Spring I would always favor constructors. So for me the discussion is mainly about choosing between what’s the best for Spring or what’s the best for your code. What would you do if you wrote your code without Spring?

    I believe if you choose to adapt your code to Spring you might as well use @Autowired or @Inject on instance variables like said before. You can always make your code Spring and CDI compliant.

    Btw if you have to many arguments in your constructor than you’ll possibly have to many dependencies and your class might not have a single responsibility then you’ll have something more important to think about then setter or constructor injection ;-). And like said before circular dependencies are evil.

  7. Pingback: Cyclic Dependency Injection and Making a Choice | Tim's Blog

  8. Javame says:

    In my opinion use Setter only for optional dependency as mentioned on How to choose between Setter vs Constructor dependency Injection

  9. It is worth mentioning that the Spring team has changed their mind long time ago, unfortunately the breakout box you quote has never been updated. This is about to be fixed now:
    https://jira.springsource.org/browse/SPR-11459

    • Steve Schols says:

      Hi Erich,

      Thanks for your reply and the JIRA link.

      Indeed, I started reading more and more about constructor injection: the use of mandatory dependencies and easier testable code. So I always wondered why Spring did advocate setter-injection. Apparently, they changed their mind as well.
      Mostly I use field injection, but that can make the code less testable.

      Either way, circular dependencies are considered bad design and are to be avoided. And in Spring that is covered correctly by throwing an Exception when circular dependencies are detected if you use constructor injection.

  10. Thanks, a nice lesson to me.

  11. Pingback: spring injection variable setter constructor | Life in USA

  12. olivia says:

    Nice article. What i’d treat “The Spring team usually advocates setter injection, as a result of massive numbers of builder arguments will get unwieldy, particularly once properties ar optional” is that constructors ar fine albeit they need multiple arguments.

  13. One of the pitfalls with setter injection is that your dependency will remain mutable, whilst with constructor injection approach the fields [can be declared] as final (immutable)

  14. Juan Diaz says:

    Setter injection and field injection is and always will be a terrible idea. If you have circular dependencies, you have a huge flaw in your design.

    > No reconfiguration and re-injection
    Create another bean with the other dependencies you may need. Re-injection is a terrible idea.

    • I do agree with the second: re-injection seems to be a terrible idea.

      But, as often as I read it, why would circular dependencies be a problem? This is something I expect my DI framework to handle. IMO, it’s a good thing: sometimes, two services are inter-dependent and I don’t want any additional layer just to pretend that I don’t have those dependencies. I just do it shamelessly and on a regular basis in CDI.

      Same for field injection. I don’t care what Martin Fowler says. I do have dependencies, and I don’t want to handle them myself. That’s what IoC is for. Can one construct my class without passing all required dependencies? Sure, just don’t. Java is pretty weak in controlling such things. There is no pattern that won’t let you create an object with one of its 15 properties missing, unless you start having big cumbersome constructors and artificial, pyramidal dependencies. Hint: the “builder” “pattern” won’t solve that.

  15. Pingback: How to refactor or fix circular reference in this case? java – Best Java Answer

  16. chromechris says:

    Awesome post my man!

  17. Miguel Munoz says:

    Circular dependencies don’t need to be a problem, and don’t necessarily mean you have a bad design. In fact, they are a tried-and-tested element of an old, trusted design pattern called model-view-controller. Here’s how it’s done safely:

    Take the table class, JTable, and its model interface, the TableModel. Each needs a reference to the other. Also, the TableModel paradoxically needs to know nothing at all about the JTable. How is this done? Simple. The JTable implements the TableModelListener, which is the class the TableModel uses to communicate with its view classes. The JTable’s setModel() method does this:

    public void setTableModel(TableModel theModel) {
    model = theModel;
    model.addTableModelListener(this);
    }

    (This is simplified a bit. The actual class allows you to replace the existing model, but you get the picture.)

    The key thing to keep in mind is that one of the two classes has to know that there’s a circular dependency, and set it up.

  18. Miguel Munoz says:

    Much of the debate about setter injection vs. constructor injection comes out of the the case of the complex class, with many objects to set, some of which are optional. There’s a lot of debate because neither approach handles this case well. So I recommend reading item 2 of Joshua Bloch’s book Effective Java. It’s called “Consider a builder when faced with many constructor parameters.” (The rest of the book is well worth reading, too.)

    Here’s the thinking. A Builder is a separate class used to construct an object. The object may be written with a single package-level constructor, so that only the public Builder class will be calling it. It’s more often written as a static inner class of the one that it builds. With a Builder class, building an instance looks something like this:

    Foo foo = new Foo.Builder(“Big Foo”, new FooModel(), new Bar())
    .formatter(new CrazyFooFormatter()) // optional element
    .logger(fooLogger) // optional, instantiated previously
    .build();

    Notice a few things. First, there’s only one semicolon. This is one large chained call.
    Notice the optional elements. The required elements are passed to the Builder’s constructor, and optional values are pass in with chained methods, but still before the Builder actually builds the instance. That last call to the build() method passes all the arguments it received to the private constructor, which can guarantee that the required fields aren’t null, while allowing null or installing default values, for the optional fields. This way, all of the fields can be declared final, even when some of them are optional. This lets us write Foo as in immutable class. And it beats writing the eight constructors that would be needed to handle three optional fields.

    Using this pattern with Spring may be a challenge, but keep in mind that you don’t need to construct the objects in-line like I did. All of these parameters could be values that were injected previously.

    There are lots of other advantages that I haven’t even mentioned, but which are discussed in the book. It’s worth checking out.

  19. Pingback: Spring的@Autowired實踐感知 | 程式前沿

  20. Pingback: java – 尝试将spring boot war部署到tomcat8时未解析的循环引用? - 算法网

Leave a reply to Steve Schols Cancel reply