Why @Autowired and Constructor Injection Differ in Spring: Execution Order & final Keyword Explained

This article explains the warning caused by @Autowired, compares field injection with constructor injection, clarifies Java's initialization order, shows how to fix the issue using constructor injection, and discusses whether adding the final modifier to injected fields is necessary.

JavaEdge
JavaEdge
JavaEdge
Why @Autowired and Constructor Injection Differ in Spring: Execution Order & final Keyword Explained

Problem Background

When using @Autowired on a field, IntelliJ IDEA may display a warning that the injected value could be null. The warning can be suppressed, but the root cause is that field injection occurs after the constructor finishes, so the field is not available during object construction.

Spring team recommends always using constructor‑based dependency injection and assertions for mandatory dependencies.

Difference Between @Autowired and Constructor Injection

@Autowired

can be applied to fields, setter methods, or constructors. Field injection works like setter injection defined in XML, while constructor injection supplies dependencies directly via the class constructor.

Java initialization order is:

static fields/blocks → instance fields/blocks → constructor → @Autowired injection

Consequently, accessing an @Autowired field inside the constructor sees a null value, which can cause a NullPointerException during bean creation.

Typical exception message:

Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘…’: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate […]: Constructor threw exception; nested exception is java.lang.NullPointerException

Solution: Use Constructor Injection

Define a constructor that receives all required beans. Spring injects the dependencies before the constructor body runs, guaranteeing that the fields are fully initialized.

@Component
public class MyService {
    private final Dependency dependency;

    @Autowired
    public MyService(Dependency dependency) {
        this.dependency = dependency;
    }
}

Why Add final ?

Spring beans are singleton by default; the instance is created once at startup. Marking a dependency field as final does not change the bean lifecycle but documents that the reference will not be reassigned after construction.

It makes the code clearer and helps static‑analysis tools detect accidental reassignment.

Reference: https://blog.csdn.net/ruangong1203/article/details/50992147

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaspringdependency-injectionConstructor InjectionAutowiredfinal
JavaEdge
Written by

JavaEdge

First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.

0 followers
Reader feedback

How this landed with the community

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.