skip to content

Constructor vs Setter vs Field Injection

Constructor injection gives you final fields, mandatory dependencies and a class you can test without Spring; setter injection suits optional collaborators; field injection hides dependencies from the compiler. Interviewers ask this to hear a reasoned preference rather than a slogan.

part ofSpring Frameworkoverview, primer and where to startread it →
on this pageshow

questions

5

What are the three styles of dependency injection in Spring, and how does each supply a bean its collaborators?

level: juniorimportance: must knowfreq 85%

answer

  1. ctor args / setter methods / field reflection
  2. single ctor since 4.3 = @Autowired optional
  3. final fields = constructor only
  4. optional+reconfigurable = setter
  5. field = discouraged

basics

~10 s

Constructor injection passes dependencies as constructor arguments. Setter injection calls setter methods after construction. Field injection sets private fields directly (via reflection), usually with @Autowired on the field.

solid answer

~30 s

Spring supports three injection styles. Constructor injection declares dependencies as constructor parameters; Spring creates the bean by calling that constructor, so the object is fully initialized and its fields can be final. Setter injection uses a no-arg constructor plus setter methods that Spring calls after instantiation — good for optional or reconfigurable dependencies. Field injection annotates the field itself with @Autowired and Spring sets it directly through reflection, bypassing any constructor or setter. Constructor injection is the Spring-recommended default because it guarantees required dependencies are present and enables immutability; field injection is discouraged because it hides dependencies and hurts testability.

code

java · 24 lines
java
// Constructor injection (recommended) — single ctor, @Autowired optional
@Service
class OrderService {
    private final PaymentGateway gateway;
    private final InventoryClient inventory;
    OrderService(PaymentGateway gateway, InventoryClient inventory) {
        this.gateway = gateway;
        this.inventory = inventory;
    }
}

// Setter injection — optional dependency
@Service
class ReportService {
    private MailSender mailSender;
    @Autowired(required = false)
    void setMailSender(MailSender s) { this.mailSender = s; }
}

// Field injection — discouraged
@Service
class NotificationService {
    @Autowired private PaymentGateway gateway; // hidden, hard to unit-test
}

go deeper

for a junior

Must name all three styles and how each delivers the dependency.

for a middle

Should know the single-constructor 4.3 rule and final-field implication.

for a senior

Explains testability and immutability trade-offs behind the recommendation.

for a principal

Frames the choice as an API/design contract about required vs optional dependencies.

**Dependency Injection (DI)** means a class does not create its own collaborators (dependencies); instead the **Spring IoC container** supplies them. Spring offers three ways to inject them. **1. Constructor injection.** Dependencies are declared as parameters of the class constructor. Spring resolves each parameter to a matching bean and calls the constructor to build the object. ```java @Service class OrderService { private final PaymentGateway gateway; OrderService(PaymentGateway gateway) { this.gateway = gateway; } } ``` Since Spring Framework 4.3, if a class has exactly **one constructor**, `@Autowired` on it is optional — Spring auto-wires it implicitly. The fields can be `final`, giving **immutability**: once built, the reference never changes. **2. Setter injection.** The bean has a no-arg constructor, and Spring calls setter methods after instantiation. ```java @Service class ReportService { private MailSender mailSender; @Autowired(required = false) void setMailSender(MailSender s) { this.mailSender = s; } } ``` Useful for **optional** dependencies (`required = false`) and dependencies you may want to **reconfigure** later. Fields cannot be `final`. **3. Field injection.** `@Autowired` (or `@Inject`/`@Resource`) is placed directly on a field; Spring sets it via **reflection**, bypassing constructors and setters. ```java @Service class BadService { @Autowired private PaymentGateway gateway; } ``` Concise but discouraged (IntelliJ even warns "Field injection is not recommended"). **Key mechanisms & terms.** - **@Autowired**: marks an injection point Spring should satisfy by type. - **IoC container**: the `ApplicationContext` that instantiates and wires beans. - **Reflection**: field injection writes even into `private final`-less fields without a public accessor. **When to use which.** Prefer constructor injection for **required** dependencies (the Spring team's official recommendation). Use setter injection for **optional/reconfigurable** ones. Avoid field injection except perhaps in test code. **Gotchas.** With multiple constructors you must mark one with `@Autowired` or Spring won't know which to use. Field injection cannot be used to build the object in a plain unit test — you'd need reflection or a Spring context — which is exactly why it hurts testability.

  • Since which Spring version is @Autowired optional on a single constructor?
    Spring Framework 4.3. If a bean class declares exactly one constructor, Spring auto-wires it without an explicit @Autowired annotation.
  • Can a field-injected dependency be final?
    No. final fields must be assigned during construction, and field injection happens after the object is constructed (via reflection), so the field cannot be final. Only constructor injection allows final.

saying these in an interview costs you the question

  • Claiming field injection is the recommended default
  • Saying you must always put @Autowired on the constructor (not since 4.3 for single-ctor)
  • Thinking setter injection allows final fields

context

open as a page

Why does the Spring team recommend constructor injection over field injection for required dependencies?

level: middleimportance: must knowfreq 80%

basics

~10 s

Constructor injection guarantees required dependencies exist at creation, lets fields be final (immutable), makes dependencies explicit, and lets you build the object in tests with plain new — no Spring or reflection needed.

open as a page

How do you model optional dependencies and disambiguate multiple constructors across the three injection styles?

level: seniorimportance: should knowfreq 45%

basics

~10 s

Optional deps: setter with @Autowired(required=false), or constructor param typed Optional<T> or annotated @Nullable. Multiple constructors: mark the one to use with @Autowired (single-ctor auto-wiring only works when there's exactly one).

open as a page

Explain the testability and immutability implications of choosing constructor versus field injection.

level: seniorimportance: should knowfreq 60%

basics

~10 s

Constructor injection lets fields be final (immutable, thread-safe) and lets tests build the object with new passing mocks. Field injection forbids final and forces tests to use reflection or a Spring context.

open as a page

How does the injection style you choose affect circular dependencies and proxy-based features like @Transactional?

level: principalimportance: nice to knowfreq 35%

basics

~20 s

Constructor injection fails fast on circular dependencies (BeanCurrentlyInCreationException), forcing a redesign. Setter/field injection can resolve cycles by wiring after construction. Proxying (@Transactional) works with all styles because Spring injects the proxy, not the raw bean.

open as a page