Blogs

SpringSource Blog

Setter injection versus constructor injection and the use of @Required

Alef Arendsen

A couple of month ago, we start publishing polls on www.springframework.org asking people to provide their feedback about Spring, some of its features and how they are using those features. The first question I posted was whether or not people were checking required dependencies and if so, what mechanisms they used. I quickly followed up on this question asking the community what transaction management strategy it used.

To my delight when I first checked the results, back in March, a lot of people told us by voting in the first poll that they were using the @Required annotation. The second poll–on transaction management, quickly showed that a lot of people were using the @Transactional annotation. Below you can find some of the results of the poll about checking required dependencies. Together with the poll on transaction management (about 30% of all respondents are using the @Transactional annotation to demarcate transaction boundaries) they consistently show that people are using Spring 2.0 a lot, which was very good news for us. Because upgrading an application that uses Spring 1.x to use Spring 2.0 shouldn't be any issue, we really hoped people would not stick to Spring 1.x and in fact, people massively upgraded.

How are you checking required dependencies

8% I check them in my business methods
9% Using init-method and an assert mechanism (c.f. Assert)
9% Using the dependency-check attribute in XML
13% I don't have to, I use constructor injection
15% Using InitializingBean and an assert mechanism
17% Using the Spring 2.0 @Required annotation
29% I do not check required dependencies

What's interesting however is that 29 percent of all people do not check required dependencies. In the forum thread that accompanied the discussion, interesting suggestions came up as to why some people weren't doing this and how people solved it otherwise. Let's review some of those.

Constructor injection

I'd like to begin with reviewing constructor injection. Any object that has a constructor that takes arguments, can (obviously) not be constructed without passing in arguments. In Java, we have a default or implicit constructor added to our class as long as we do not add one ourselves. This default or implicit constructor does not take arguments, so as long as you do not add a constructor with arguments at all, or specifically add one without any arguments, it will be possible for Spring (or any other user of your class for that matter) to instantiate your class without passing it anything.

In other words, we can force a user of our class (again, this might be Spring but it could also be a unit test that instantiates your class directly) to instantiate it while passing in arguments.

public class Service {

  public Collaborator collaborator;

  // constructor with arguments, you *have* to
  // satisfy the argument to instantiate this class
  public Service(Collaborator collaborator) {
    this.collaborator = collaborator;
  }
}

We can use this to our advantage when in need to check required dependencies. If we modify the above code example to include assertions, we are 100% sure the class will never be instantiated without its collaborators injected:

public Service(Collaborator collaborator) {
  if (collaborator == null) {
    throw new IllegalArgumentException("Collaborator cannot be null");
  }
  this.collaborator = collaborator;
}

In other words, we do not need a dependency checking mechanism if we're using constructor injection in combination with an assertion mechanism like I've showed above.

Why do people not use constructor injection mostly

The question of course now is, why so few people are using constructor injection to enforce required dependencies, if it is the simplest way to get the job done! There are two reasons for this–one is a bit more historical, the other being the nature of the Spring Framework itself.

Historical reasons

Early 2003, when Spring was first published as an open source project, it primarily focused on setter injection. Other frameworks also pioneered ways of doing dependency injection and one of those was PicoContainer, which strongly focused on constructor injection. Spring maintained its focus on setter injection because at the time, we believed that the lack of default arguments and argument names for constructor arguments resulted in less clarity for developers. We however also implemented constructor injection, to be able to offer that feature to developers that wanted to instantiate and manage objects they didn't control.

This is one of the reasons why you're seeing a lot of setter injection throughout the Spring Framework itself. The fact that setter injection was used in Spring itself, as well as us advocating it mostly also caused many pieces of third-party software to start using setter injection as well as blog and articles to start mentioning setter injection.

(By the way, do people still remember type 1, 2 and M inversion of control ;-) )

Frameworks need to be a lot more configurable

The second reason why 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. This is mostly because frameworks that need to be configured often contain lots of optional values. Making optional values configurable using constructor injection would lead to needless clutter and proliferating constructors, especially when used in combination with class inheritance.

For those exact two reasons, 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 (you're application code is less likely to be used in many situations, which would require configurable properties). Second of all, application code uses class inheritance a lot less often than framework code does. Specialization in an application does not occur as often in application code as it does in framework code for example–again the number of use cases in which application code is far less.

So what should you use?

We usually advise people to use constructor injection for all mandatory collaborators and setter injection for all other properties. Again, constructor injection ensures all mandatory properties have been satisfied, and it is simply not possible to instantiate an object in an invalid state (not having passed its collaborators). In other words, when using constructor injection you do not have to use a dedicated mechanism to ensure required properties are set (other than normal Java mechanisms).

One of the other arguments for not using constructor injection is the lack of argument names in constructors and the fact that these do not appear in the XML. I would argue that in most applications, this does not matter that much. First consider the variant that uses setter injection:

<bean id="authenticator" class="com.mycompany.service.AuthenticatorImpl"/>

<bean id="accountService" class="com.mycompany.service.AccountService">
  <property name="authenticator" ref="authenticator"/>
</bean>

This version mentions the authenticator as a property name as well as a bean name. This is the pattern that I frequently encounter. I would argue that while using constructor injection, the lack of constructor argument names (and those not appearing in XML), doesn't really confuse us a lot.

<bean id="authenticator" class="com.mycompany.service.AuthenticatorImpl"/>

<bean id="accountService" class="com.mycompany.service.AccountService">
  <constructor-arg ref="authenticator"/>
</bean>

Using the alternative mechanisms

That brings us back to the topic of this blog entry, which also included a mention of @Required. This the new Spring 2.0 annotation we introduced back in 2006. @Required allows you to instruct Spring to check required dependencies for you. In case you are not in the position to use constructor injection, or for whatever other reasons, you prefer setter injection, @Required is the way to go. Annotation a property's setter an registering the RequiredAnnotationBeanFactoryPostProcessor as a bean in your application context is all you need to do:

public class Service {

  private Collaborator collaborator;

  @Required
  public void setCollaborator(Collaborator c) {
    this.collaborator = c;
  }
}
<bean class="org.sfw.beans.factory.annotation.RequiredAnnotationBeanFactoryPostProcessor"/>

Other mechanisms to check required dependencies

There are a few other mechanisms to enforce the checking of required dependencies. Most of those rely on Spring's ability to allow you to get callbacks at certain points in the construction an initialization of an object, such as the Spring InitializingBean interface or Spring's an arbitrary init method you can configure in the XML (using the init-method attribute). Those all resemble the use of constructor injection a lot, with the difference that you are relying on Spring to call the method in which the assertions take place for you.

public class Service implements InitializingBean {

  private Collaborator collaborator;

  public void setCollaborator(Collaborator c) {
    this.collaborator = c;
  }

  // from the InitializingBean interface
  public void afterPropertiesSet() {
    if (collaborator == null) {
      throw new IllegalStateException("Collaborator must be set in order for service to work");
    }
  }
}

Another mechanism, similar to @Required in Java is the dependency-check attribute in XML, which strangely enough is not used all that much. Enabling the dependency check by tweaking this attribute (it's turned off by default) will tell Spring to start checking certain dependencies on beans. Refer to the reference for more information about this features.

So why NOT check required dependencies

There are a lof of people that actually do not check if dependencies have been accurately set. The biggest reason people gave for not doing so is because they would find out quickly enough is they fired up the ApplicationContext and somehow used the classes that had dependencies. This is of course very true. If you're using Spring's integration testing support for example, you can have Spring load up an application context for you. If you're also making sure some of the actual code gets tested in your integration test, you can probably pretty much guarantee all the dependencies the classes need to work are set. It is an approach that bugs me a little bit though. You have to be confident in your test cases covering your code enough though, because if your tests do not test the code that depends on the collaborators being set, you're screwed, as you might not detect things! Of course a smoke test when you are deploying your application would probably do the trick right then and there, but I wouldn't want to be the one that only finds out about missing dependencies at runtime!

Conclusion

There is a lot to be said about constructor injection versus setter injection and I know a lot of people still prefer setter injection. I think though (and with me a lot of people) that constructor injection in combination with checking dependencies in your constructor is the better way (for code that does not have a lot of optional and configurable values or collaborators) to enforce checking of required dependencies. Combining this with final fields immediately gives you the other benefit of increased safety in a multi-threaded environment and because usually that does not prove to be a big deal anyway, I'm not going to touch on that in this blog entry.

There are situations in which I would not use constructor injection. One of those for example is a class with a lot of dependencies or other configurable values. I personally do not consider a constructor with 20 arguments as a good example of nice code. Of course, the question is, if a class with 20 dependencies does not have too many responsibilities…

One thing is for sure–enforcing required dependencies by checking them in your business methods is something I would certainly not do.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

31 responses


  1. We need parameter name annotations on constructors! The reason I don't use constructor injection is it makes the XML very uninformative compared to setters.


  2. We've taken the Spring annotation @Required concept and expanded upon it for our JA-SIG CAS project.

    For CAS, we've defined a few annotations:
    @NotNull – an object must have a value set.
    @NotEmpty -a collection or array cannot be null or empty (i.e. size > 0)
    @GreaterThan – the value of the field (currently int only) must be greater than the provided value.
    @IsIn – the value of the field (currently int) must be one of the provided options

    You can configure your spring-managed beans as usual (it should work with both Constructor and Property Injection). You merely need to include the BeanPostProcessors for each annotation in your Spring configuration file.

    If you're interested, the source code can be found here:
    http://developer.ja-sig.org/source/browse/jasigsvn/cas3/trunk/cas-server-core/src/main/java/org/jasig/cas/util/annotation

    You would use it like this:

    public class Test {
    @NotNull
    private Object myPrivateObject;

    public void setMyPrivateObject(final Object object) {
    this.myPrivateObject= object;
    }
    }


  3. Asd,

    In general, you're right. My experience shows that this is not too big a deal for most application objects. See my update to the article for more information on this.


  4. Transaction: i willingly avoid transaction annotations. I do see the rationnals beyond it, but the XML declaratives is my first choice because:
    1- it avoid some dependencies to spring annotations packages to service layer classes that i would really prefere as more POJO friendly as possible.
    2- XML declarations allows you to change a subsystem TXN behaviour without changing the code. Of course we do not change TXN declarations on a daily basis.
    3- TXN logic is uniquely defined in a single file, very clear.

    Of course we could mix the different ways of doing TXN which is, in my eyes even more confusing.

    Dependencies checks:
    I prefer constructor-args for the reasons you mentions. But i also like to test my POJO outside of the Spring Bean Factory, so i cannot assum they are correctly initialized.


  5. I tend to favor constructor injection whenever I can because it allows me to use immutable objects, whose inherent thread safety makes them good candidates for sharing.

    D.


  6. Here's my dirty little secret: There are still some controlled situations in which I am comfortable using Autowire By Name. Obviously, a component that relies on constructor injection can't be used in these situations.


  7. The cleanest solution to be certain that your dependencies get set, is to use the constructor injection technique in conjunction with final members (to overcome multi-core concurrency issues).

    People that just rely on their testsuite to be certain there would not be any issues in production environment, is just crazy. How can they be certain in multi-core environments that there aren't going to be visibility problems? And even if so, you have to have a full regression testsuite with 100% coverage.. and that's just not possible to achieve.

    If you are using setter injection, you need to make your members volatile anyway… just (like above) to be sure that no visibility problems will occur regarding concurrency in multi-core environments.


  8. Mostly because of the fact that wiring typically happens at application startup and in a single thread, chances are very very slim that you end up with visibility issues and usually it is pretty much impossible to end up in such a situation even. Of course, making fields final (for constructor injection) and volatile (for setter injection) helps, but again, typically, there are no issues with visibility.

    Rob Harrop recently gave a talk about concurrency and Spring. If this comes online (at Parleys.com) I would recommend everybody to have a look, because (from what I've seen–I've only seen half of it), it cleared up many things.

    I agree that solely depending on a test suite to check required dependencies is not the best way of doing it, not because of visibility reasons though.


  9. [quote comment="33582"]We've taken the Spring annotation @Required concept and expanded upon it for our JA-SIG CAS project.
    [/quote]

    Scott,

    those are certainly interesting techniques. I encourage everyone to take a look at how Scott and his team have implemented these techniques, as they're certainly using some interesting and very useful Spring extension points!


  10. Hi Alef,

    [quote comment="33620"]Mostly because of the fact that wiring typically happens at application startup and in a single thread, chances are very very slim that you end up with visibility issues and usually it is pretty much impossible to end up in such a situation even. Of course, making fields final (for constructor injection) and volatile (for setter injection) helps, but again, typically, there are no issues with visibility.
    [/quote]
    With Java 5 and higher the chance of visibility issues in Spring is reduced because of the 'piggy backing on synchronization' behavior the applicationcontext provides. There is a happens before edge between acquiring a lock when a bean is read from the applicationcontext, and releasing the lock when the bean is written to the applicationcontext. When there is a happens before edge, there are no visibility problems.

    [quote]
    Rob Harrop recently gave a talk about concurrency and Spring. If this comes online (at Parleys.com) I would recommend everybody to have a look, because (from what I've seen–I've only seen half of it), it cleared up many things.
    [/quote]
    I would like to see it.


  11. Remember the small prototype we wrote using ParameterNameDiscoverer?


  12. Alef,
    From a simple OO design point of view, what you recommend about the use of constructor injection makes perfect sense. I allowed myself to be swayed into using setter construction by the message that i21 was putting out back when we started using Spring, but what I learned back in my C days is that classes should prevent, as much as possible, the construction of instances with invalid state. In these days of increasingly anemic models, the least a class can do to earn it's wage is to act as gatekeeper over its own state.
    In the end it's much better to use the simplest, least Spring-dependent way of defining which data members (including dependencies) are required and which are not. Thanks for bringing up this matter again.


  13. That should have read 'C plus-plus' but somehow the ' ' disappeared.


  14. 强烈抗议�支�中文,�外怎么没有一点国际化精神呢?

    This website should surport Chinese!Thank you!


  15. Alef,

    Thanks for the thoughtful treatment of these two alternatives. Constructor vs. setter injection is something that often becomes a matter of religion. It's not nearly so black-and-white, and I think that (amongst your other points) drawing a distinction between the needs of application code vs. framework code is spot on. While I strongly prefer constructor injection whenever appropriate, there are certainly contexts where setter injection is preferable (optional parameters are the obvious case here). It's worth pointing out that these two approaches are not mutually exclusive either. I often mix and match constructor and setter injection, e.g.:



    This is an overly simple example (one would likely never declare such a bean), but it expresses the idea.

    As you mention, it translates to Java code that properly leverages constructors to ensure an object is always in a valid state:

    BlogCommenter commenter = new BlogCommenter("Chris", "Beams");
    commenter.setMiddleInitial('S');

    This reduces the likelihood of NullPoninterExceptions down the road, and specifies a clear contract to users of your class as to how it should be used. No guesswork as to which setters 'must' be called, etc. These benefits, IMHO, outweigh the decreased readability caused by the fact that constructor args do not have names in the spring configuration XML, particularly because classes may be used in contexts outside Spring configuration. In these cases, we want to rely on the language as much as possible to inform us about how to use the class. Constructors are the natural choice here.

    Now, if only the p: namespace allowed for some syntactic sugar around constructor args ;-)

    - Chris


  16. Looks like my XML example from the comment above got treated as HTML. Here it is again (very simple, just demonstrating combining constructor and setter injection within a single bean declaration):

    <bean id="blogCommenter" class="org.example.BlogCommenter">
    <constructor-arg value="Chris"/> <!– first name, required –>
    <constructor-arg value="Beams"/> <!– last name, required –>
    <property value="S"/> <!– middle initial, optional –>
    </bean>


  17. Hey Chris,

    thanks for your comments. I'll try to update the blog post when I have time, because mentioning the possibility to mix constructor injection and setter injection is definitely something that should have been done from the start.


  18. My preference is to use constructors for manditory arguments and IntelliJ's @NotNull annotation to check arguments which cannot be null. I also use setters for optional arguments. (With @NotNull as approriate)

    Does anyone know how to configure Spring to use the Common Annotations 1.0 which come with Java 6. e.g. @PostConstruct, @PreDestroy, @Resource and @ConstructorProperties ?


  19. My preference for beans with a long list of constructors args is to use a configuration bean. As in

    public class Foo{
    private final Service service;
    private final SomethingElse somethingElse;

    public Foo(FooOptions opts){
    assert( null != opts );

    service = opts.service;
    somethingElse = opts.somethingElse;
    //don't perform checks on opts, instead on local vars, as callers may have changed opts in the meantime
    assert( null != service );
    assert( null != somethingElse );
    }
    }

    public class FooOptions{
    public Service service;
    public SomethingElse somethingElse;
    get/set….
    }

    You could also use the getters/setters in the options bean.

    IMHO the advantage of this approach is that if subclasses need further args, just subclass the options bean, and no further changes to your classes are required.

    It would be nice if Java supported automatic generation of constructor options beans (ie like named arguments I guess), or allowed inner classes without the need for an instance of the outer class so that these options can be kept in the same file.

    Another approach is using an interface:

    public class Foo {
    public Foo(FooOpts opts) {
    //..assert(…)
    service = opts.getService();
    somethingElse = opts.getSomethingElse();
    //..assert(…)
    }

    public interface FooOpts {
    public SomethingElse getSomethingeElse();
    public Service getService();
    }
    }

    and an example usage might be:

    Foo foo = new Foo(new Foo.FooOpts(){
    public Service getService() {
    return "My Service";
    }
    public SomethingElse getSomethingElse() {
    return "SomethingElse";
    }
    });

    My personal take on setters vs constructors, is that the setters clutter up the API you are trying to expose, and you also end up with a lot of boring boilerplate get/set. IMHO objects should expose business logic, and not all the other junk for settings the object up. In the case of an options object, it doesn't contain any business logic, its just a transfer object, in which case get/set is fine and doesn't add to the confusion


  20. Oh, and using the seperate FooOpts concreate class instead of the interface is easier for spring integration, as you just create another config entry for the FooOpts bean, and pass that in as a constructor arg to the Foo bean.


  21. Aside from constructor injection, how else can someone ensure objects are in valid states without coupling it to Spring? I have avoided @Required and initializingBean interface because I will have to take the same classes later and plug them into a different framework that doesn't use it.


  22. Create your custom annotaion:-

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Mandatory {
    }

    Register this annotation with the RequiredAnnotationBeanPostProcessor

    You can now use @Mandatory on the setter methods.


  23. The xml config for @Mandatory did not come up, this time posting without the angular brackets

    bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"
    p:requiredAnnotationType="Mandatory"


  24. I use setter dependency injection in my big project and constructor injection really do bother me because although this is just an application, our architecture uses a lot of inheritance and interfaces to accomplish things.

    By the way, I can see one class with 40 or more dependencies. This is what we call a Façade.

    Best regards,
    George.


  25. Hi,very good web site. Thanks.


  26. Hi, very good web site. Thanks.


  27. great post..

    i also found a spoon fed tutorial using @Required annotation

    http://www.adobocode.com/spring/how-to-use-required-annotation-in-spring

    hope it helps


  28. Maybe it's ok to just think of Field injection as an ad-hoc Service Locator.
    Certainly gives you more freedom.

    This article goes more in depth to that suggestion…
    http://tech.finn.no/2011/05/13/dependency-injection-with-constructors/


  29. Using setter injection solves cyclic dependencies.


  30. I always choose later because of readability. This link also has some good points


  31. Good Explanation except in the applicationContext.xml, it shall be
    rather than

2 trackbacks

Leave a Reply