Autowired says field injection not recommended
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When tools warn that field injection is not recommended, they are pointing to maintainability and testability issues, not syntax errors. Field injection works, but it hides required dependencies and makes classes harder to construct safely. Constructor injection is usually the preferred pattern in modern Spring applications.
Why Field Injection Is Discouraged
Field injection with @Autowired on member variables has drawbacks:
- Dependencies are not visible in constructor signature.
- Fields cannot be
final. - Unit tests require reflection or full Spring context.
- Missing dependency errors appear later in runtime path.
Example of field injection:
It works, but dependency visibility is weak.
Preferred Constructor Injection
Constructor injection makes dependencies explicit and immutable.
With one constructor, Spring injects automatically without @Autowired annotation.
Why Constructor Injection Improves Testing
Classes with constructor injection are easy to test directly without Spring container.
This keeps unit tests fast and isolated.
What About Optional Dependencies
If dependency is optional, use one of these patterns:
- Constructor parameter as
Optional<T>. - Provide default implementation bean.
- Use feature flags with explicit strategy objects.
Avoid nullable hidden fields where absence is discovered too late.
@RequiredArgsConstructor with Lombok
If constructor boilerplate is a concern, Lombok can generate constructor for final fields.
This keeps explicit dependency design while reducing manual code.
Migrating from Field Injection
Constructor Injection for Optional Dependencies
When dependency is optional, keep constructor injection and pass an ObjectProvider so optional behavior remains explicit.
This preserves testability and avoids hidden nullable fields while still supporting optional beans.Incremental migration strategy:
- Pick one component at a time.
- Move field dependencies to constructor.
- Mark dependencies
final. - Update tests to direct instantiation.
This approach avoids large risky refactors and improves code quality steadily.
When Field Injection Might Still Appear
Legacy codebases and quick prototypes may still use field injection. If immediate migration is not possible, at least document dependencies and plan conversion in maintenance backlog.
For production-critical modules, prioritize constructor migration first because those components benefit most from strong dependency clarity.
Team-Wide Convention Enforcement
To prevent regression into field injection, add static-analysis checks in CI and fail pull requests that introduce new field-level @Autowired usage in application modules. This keeps dependency style consistent and reinforces constructor-first architecture over time.
If full enforcement is too disruptive initially, run in warning mode and migrate gradually by module.## Common Pitfalls
- Treating warning as stylistic only and ignoring design impact.
- Keeping hidden dependency graphs across large services.
- Mixing field and constructor injection in same class.
- Assuming full integration tests replace need for unit-testable design.
- Delaying migration until dependency problems become runtime incidents.
Summary
- Field injection works but reduces visibility and testability.
- Constructor injection is the recommended default in Spring.
- Explicit dependencies improve immutability and error detection.
- Tests become simpler when services can be instantiated directly.
- Migrate legacy field injection gradually with clear priorities.

