Backend Development 7 min read

Why Field Injection in Spring Is Risky and How Constructor Injection Solves It

The article explains how field injection in Spring can cause null‑pointer exceptions, break immutability, violate design principles, and hide circular dependencies, and demonstrates that using constructor injection (with optional @Lazy) provides safer, more maintainable dependency management.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Why Field Injection in Spring Is Risky and How Constructor Injection Solves It

1. Introduction

Dependency injection allows an object to use its dependencies without manually creating them; it is a core feature of Spring.

Spring supports three injection types: constructor injection, setter injection, and field injection (using @Autowired ). Field injection is simple but can cause problems.

2. Problems Caused by Field Injection

2.1 Null‑Safety

If a dependency is not initialized, field injection can lead to NullPointerException . Example code:

<code>@Repository
public class PersonDAO {}

@Service
public class PersonService {
  // @Autowired
  @Resource
  private PersonDAO dao;
  public String toString() {
    return "PersonService [dao=" + dao + "]";
  }
}
</code>

When the container starts, using @Autowired without a bean causes startup errors; using @Resource also leads to NPE at runtime.

Creating the service manually also results in NPE:

<code>PersonService ps = new PersonService();
ps.xxx();
</code>

Constructor injection avoids this by requiring the dependency:

<code>private final PersonDAO dao;
public PersonService(PersonDAO dao) {
  this.dao = dao;
}
</code>

2.2 Immutability

Field injection prevents creation of immutable classes because final fields cannot be injected; constructor injection is needed for immutable dependencies.

2.3 Design Issues

Using field injection can violate the Single Responsibility Principle by adding unnecessary dependencies, and it can hide circular dependencies.

Example of circular dependency with field injection:

<code>@Component
public class A {
  @Autowired
  private B b;
}

@Component
public class B {
  @Autowired
  private A a;
}
</code>

Spring may allow this circular dependency, but from Spring Boot 2.6 onward it throws BeanCurrentlyInCreationException .

Note: In plain Spring circular dependencies are allowed by default, but Spring Boot 2.6+ disallows them.

Solution: use constructor injection with @Lazy on one side.

<code>public A(@Lazy B b) {
  this.b = b;
}
</code>

In summary, prefer constructor injection for required dependencies and use setter injection only for optional ones.

Springdependency injectionConstructor InjectionField InjectionCircular DependencyNull Safety
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.