Backend Development 5 min read

Understanding @Autowired Injection Issues and Alternative Approaches in Spring

The article explains common problems with Spring's @Autowired injection, compares it with @Resource, and presents alternative injection methods—including setter, constructor, and Lombok-based approaches—while providing code examples and best‑practice recommendations for reliable bean initialization.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Understanding @Autowired Injection Issues and Alternative Approaches in Spring

Spring's dependency injection can cause initialization problems, especially when @Autowired fields are processed after subclass constructors, potentially leading to NullPointerExceptions. The article first outlines the Java class initialization order: static fields and blocks of the parent class, then those of the child, followed by instance fields, instance blocks, and constructors.

It highlights that @Autowired injection is queued after the subclass constructor, and Spring IoC does not check for null beans, so misuse may cause runtime errors. The discussion then compares @Autowired (Spring‑specific) with @Resource (JSR‑250 standard), noting that @Autowired creates a strong coupling to the Spring framework, while @Resource is more portable.

Additional concerns include excessive dependencies that violate the Single Responsibility Principle and the inability to inject immutable objects via field injection. The article suggests balancing loose coupling with practical development needs.

Alternative injection methods are presented. Setter injection using @Autowired on a setter method is shown:

@RestController
public class TestController2 {
    ITestService testService;
    /* Based on setter injection */
    @Autowired
    public void setTestService(ITestService iTestService) {
        this.testService = iTestService;
    }
    @GetMapping("/status2")
    public Result
status() {
        return testService.status();
    }
}

Constructor injection, which avoids circular dependencies and is considered the most reliable, is demonstrated:

@RestController
public class TestController1 {
    ITestService testService;
    /* Based on constructor injection */
    public TestController1(ITestService iTestService) {
        this.testService = iTestService;
    }
    @GetMapping("/status1")
    public Result
status() {
        return testService.status();
    }
}

A simplified constructor approach using Lombok's @RequiredArgsConstructor is also described. After adding the Lombok dependency:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.2</version>
</dependency>

the class can be written as:

@RestController
@RequiredArgsConstructor
public class TestController3 {
    private final ITestService testService;
    @GetMapping("/status3")
    public Result
status() {
        return testService.status();
    }
}

The article concludes that constructor injection, especially when combined with Lombok, provides a concise and reliable way to manage dependencies, while setter injection remains a viable alternative when needed.

JavaSpringdependency injectionConstructor InjectionAutowiredResourceLombok
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

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.