Setter DI vs. Constructor DI in Spring?

Solution 1:

When it comes to Spring specific pros and cons:

  • Constructor injection (from the definition) does not allow you to create circular dependencies between beans. This limitation is actually an advantage of constructor injection - Spring can resolve circular dependencies when setter injection is used without you even noticing.

  • On the other hand if you use constructor injection CGLIB is not able to create a proxy, forcing you to either use interface-based proxies or a dummy no-arg constructor. See: SPR-3150

Solution 2:

You should be deciding based on design considerations, not tool (Spring) considerations. Unfortunately, Spring has trained us to use setter injection because when it was originally conceived, there was no such thing as an "annotation" in Java, and in XML, setter injection works and looks much better. Today, we're freed from those constraints, thus allowing it to be a design decision again. Your beans should use constructor injection for any dependencies that are required by the bean and setter injection for dependencies that are optional and have a reasonable default, more or less as OOD has been telling us from the beginning.

Solution 3:

Constructor Injection: We are injecting the dependencies through Constructor.

Generally we can use for Mandatory dependencies.

If you use the Constructor injection there is one disadvantage called "Circular Dependency".

Circular Dependency: Assume A and B. A is dependent on B. B is dependent on A. In this constructor injection will be failed. At that time Setter injection is useful.

If Object state is not inconsistent it won't create Object.

Setter Injection: We are injecting the dependencies through Setter methods.

This is useful for Non-Mandatory dependencies.

It is possible to re injecting dependencies by using Setter Injection. It is not possible in Constructor injection.

Solution 4:

As per the content from spring.io from Spring 5 onwards

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Here is the link for above quote

But, all of the injections types are available and none of them are deprecated. At a high-level you get the same functionality across all injection types.

In short, choose the injection type that works best for your team and project.

Recommendations from the Spring team and independent blog posts will vary over time. There is no hard-fast rule.

If a particular injection style was not recommended by the Spring team, then they would mark it as deprecated or obsolete. That is not the case with any of the injection styles.

Solution 5:

Prefer setter injection.

Think what would be without spring (as Ryan noted). Would you pass the dependencies in constructor? If there are too many dependencies this seems wrong. On the other hand the constructor may be used to enforce the valid state of the object - require all dependencies and verify if they are non-null.

Proxies are another thing (As Tomasz noted) - you will need a dummy constructor which defeats the whole idea.

There is a 3rd option btw - field injection. I tend to be using that, although it is not such a good design decision, because it saves an extra setter, but if this is used outside of spring I will have to add the setter.