Constructor vs Setter vs Field Injection in Spring Boot: Key Differences
constructor injection injects dependencies via a class constructor and is preferred for mandatory dependencies and immutability. Setter injection uses setter methods allowing optional dependencies and flexibility, while field injection injects directly into fields but is less recommended due to testability and design concerns.Quick Comparison
Here is a quick side-by-side comparison of constructor, setter, and field injection in Spring Boot.
| Factor | Constructor Injection | Setter Injection | Field Injection |
|---|---|---|---|
| Injection Method | Via constructor parameters | Via setter methods | Directly on fields |
| Dependency Requirement | Mandatory dependencies | Optional or changeable dependencies | Usually mandatory but less explicit |
| Immutability | Supports immutable fields | Fields can be mutable | Fields can be mutable |
| Testability | Easier to test with explicit dependencies | Testable but requires setters | Harder to test, uses reflection |
| Spring Recommendation | Preferred and recommended | Acceptable for optional dependencies | Not recommended, considered bad practice |
| Null Safety | Dependencies are guaranteed non-null after construction | Dependencies can be null if setter not called | Dependencies can be null if injection fails |
Key Differences
Constructor injection requires all dependencies to be provided when the object is created. This makes the dependencies explicit and the object immutable after creation, which improves code safety and clarity. Spring automatically calls the constructor with the required beans.
Setter injection uses setter methods to inject dependencies after the object is created. This allows optional dependencies or changing dependencies later but can lead to partially initialized objects if setters are not called. It also makes the object mutable.
Field injection injects dependencies directly into private fields using reflection and annotations like @Autowired. While it reduces boilerplate code, it hides dependencies, makes testing harder, and breaks encapsulation. For these reasons, Spring recommends constructor injection over field injection.
Code Comparison: Constructor Injection
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ServiceA { private final ServiceB serviceB; @Autowired public ServiceA(ServiceB serviceB) { this.serviceB = serviceB; } public String serve() { return "ServiceA uses " + serviceB.action(); } } @Component class ServiceB { public String action() { return "ServiceB"; } }
Code Comparison: Setter Injection Equivalent
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class ServiceA { private ServiceB serviceB; @Autowired public void setServiceB(ServiceB serviceB) { this.serviceB = serviceB; } public String serve() { return "ServiceA uses " + serviceB.action(); } } @Component class ServiceB { public String action() { return "ServiceB"; } }
When to Use Which
Choose constructor injection when dependencies are mandatory and you want immutable, clear, and testable code. It is the best practice and recommended by Spring.
Choose setter injection when dependencies are optional or might change after object creation, but be cautious about partial initialization.
Avoid field injection because it hides dependencies, reduces testability, and breaks encapsulation, making your code harder to maintain.