Understanding Dependency Injection Types in Spring: Constructor, Setter, and Field Injection
This article explains Spring's three dependency injection methods—constructor‑based, setter‑based, and field‑based—illustrates each with code examples, discusses why field injection is discouraged, and recommends using constructor injection for required dependencies and setter injection for optional ones.
Spring officially discourages the use of @Autowired field/property injection, and many companies have banned it in new projects.
Types of Dependency Injection
Spring defines three main injection styles:
Constructor‑based injection
Setter‑based injection
Field‑based injection
2.1 Constructor‑based Injection
Mark the class constructor with @Autowired (or omit the annotation) and list the required beans as parameters. This allows the injected fields to be final , guaranteeing immutability.
@Component
public class ConstructorBasedInjection {
private final InjectedBean injectedBean;
@Autowired
public ConstructorBasedInjection(InjectedBean injectedBean) {
this.injectedBean = injectedBean;
}
}The same pattern can be used without the annotation, as shown in the Spring documentation.
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private MovieFinder movieFinder;
// a constructor so that the Spring container can inject a MovieFinder
public SimpleMovieLister(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic omitted...
}2.2 Setter‑based Injection
Annotate a setter method with @Autowired . After the bean is instantiated (usually via a no‑arg constructor), Spring calls the setter to inject the dependency.
@Component
public class SetterBasedInjection {
private InjectedBean injectedBean;
@Autowired
public void setInjectedBean(InjectedBean injectedBean) {
this.injectedBean = injectedBean;
}
}As with constructor injection, the @Autowired annotation can be omitted.
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
// business logic omitted...
}2.3 Field‑based Injection
Directly annotate a field with @Autowired . Spring sets the field after the bean is instantiated.
@Component
public class FieldBasedInjection {
@Autowired
private InjectedBean injectedBean;
}While concise, this approach has several drawbacks:
3.1 Cannot Declare Immutable Fields
Fields marked final cannot be injected, so immutable dependencies require constructor injection.
3.2 Violates Single‑Responsibility Principle
Field injection hides the number of dependencies, making it easy to accumulate many hidden dependencies and ignore design signals such as a large constructor.
3.3 Tight Coupling to the DI Container
Classes become dependent on the Spring container for instantiation; they cannot be created outside the container without reflection, complicating unit testing.
3.4 Hides Dependencies
Dependencies are not exposed via constructors or setters, reducing code readability and maintainability.
Conclusion
Field injection should be avoided. Prefer constructor injection for required, immutable dependencies and setter injection for optional ones. This promotes clearer design, better testability, and adherence to SOLID principles.
References
Field injection is not recommended – Spring IOC by Marc Nuri
Spring official documentation 1.4. Dependencies
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.