The following are the types of dependency injections (DI) that could be injected into your application:
- Constructor-based dependency injection
- Setter-based dependency injection
- Field-based dependency injection
The constructor injection pattern
@Service public class BasedInjection { private final InjectedBean injectedBean; @Autowired public BasedInjection(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
Advantages
- It is more suitable for mandatory dependencies, and it makes a strong dependency contract
- It provides a more compact code structure than others
- It supports testing by using the dependencies passed as constructor arguments to the dependent class
- It favors the use of immutable objects, and does not break the information hiding principle
Disadvantages
- It may cause circular dependency. (Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection).
- Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.
The setter injection pattern
@Service public class BasedInjection { private InjectedBean injectedBean; @Autowired public void setInjectedBean(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
Advantages
- It is more readable than the constructor injection
- It solves the circular dependency problem in the application
- It allows costly resources or services to be created as late as possible, and only when required
- It does not require the constructor to be changed, but dependencies are passed through public properties that are exposed.
- It makes objects of that class amenable to reconfiguration or re-injection later.
Disadvantages
- Security is lesser in the setter injection pattern, because it can be overridden
- A setter-based dependency injection does not provide a code structure as compact as the constructor injection
- Not-null checks must be performed everywhere the code uses the setter dependency.
The Field Injection Pattern
@Service public class BasedInjection { @Autowired private InjectedBean injectedBean; }
Advantages
- It is very short, concise, there is no boilerplate code.
- The code is easy to read and navigate
Disadvantages
- You cannot create immutable objects, as you can with constructor injection
- Your classes have tight coupling with your DI container and cannot be used outside of it
- Your classes cannot be instantiated (for example in unit tests) without reflection. You need the DI container to instantiate them, which makes your tests more like integration tests
- Your real dependencies are hidden from the outside and are not reflected in your interface (either constructors or methods)
- It is really easy to have like ten dependencies. If you were using constructor injection, you would have a constructor with ten arguments, which would signal that something is fishy. But you can add injected fields using field injection indefinitely. Having too many dependencies is a red flag that the class usually does more than one thing, and that it may violate the Single Responsibility Principle.
According to Spring document, Constructor-based or setter-based DI is recommended. The constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.
The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null
. Furthermore, constructor-injected components are always returned to the 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.
References:
- Spring Core v 5.x- Dependency Injection – https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-collaborators
- Circular Dependencies in Spring – https://www.baeldung.com/circular-dependencies-in-spring
- Field Dependency Injection Considered Harmful – https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/
- Field injection is not recommended – Spring IOC – https://blog.marcnuri.com/field-injection-is-not-recommended/
- What exactly is Field Injection and how to avoid it?