Dependency Injection in Spring Boot

Field Injection vs Setter Injection vs Constructor Injection

Dependency Injection (DI) is the process where the Spring Container creates objects (beans) and injects their dependencies automatically instead of the class creating them itself.

OrderService  --->  PaymentService

OrderService depends on PaymentService.

Spring will:
1. Create PaymentService
2. Create OrderService
3. Inject PaymentService into OrderService

Object Creation and Dependency Injection Flow

Application Start
       │
       ▼
Spring Boot ApplicationContext Created
       │
       ▼
Component Scan
       │
       ▼
Bean Definitions Registered
       │
       ▼
Spring Container Creates Beans
       │
       ▼
Dependencies Identified
       │
       ▼
Dependencies Injected
       │
       ▼
Bean Ready to Use

Field Injection

@Service
public class OrderService {

    @Autowired
    private PaymentService paymentService;

}

Flow

Step 1: Spring creates PaymentService
Step 2: Spring creates OrderService
Step 3: Spring uses reflection to set field
OrderService orderService = new OrderService();

Reflection
↓

orderService.paymentService = paymentService

Advantages

✔ Simple
✔ Less code

Problems

❌ Hard to test
❌ Hidden dependency
❌ Breaks immutability
❌ Uses reflection

Setter Injection

@Service
public class OrderService {

    private PaymentService paymentService;

    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

Flow

Step 1: Spring creates PaymentService
Step 2: Spring creates OrderService
Step 3: Spring calls setter method
OrderService orderService = new OrderService();
orderService.setPaymentService(paymentService);

Advantages

✔ Optional dependencies
✔ Can modify dependency later
✔ Allows validation logic

Problems

❌ Dependency may remain null
❌ Object can be in invalid state

Constructor Injection

@Service
public class OrderService {

    private final PaymentService paymentService;

    public OrderService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }
}

Flow

Step 1: Spring creates PaymentService
Step 2: Spring calls constructor
OrderService orderService =
        new OrderService(paymentService);

Advantages

✔ Immutable
✔ Clear dependencies
✔ Best for unit testing
✔ Recommended by Spring

Comparison Table

Feature Field Injection Setter Injection Constructor Injection
Dependency visibility Hidden Visible Very clear
Immutability No No Yes
Testing Hard Medium Easy
Optional dependency No Yes Possible
Spring recommendation Avoid Sometimes Best

Difference Between Field Injection and Setter Injection

Field Injection

@Autowired
private PaymentService paymentService;
Spring injects dependency directly into the field using reflection.
No method is involved.

Setter Injection

@Autowired
public void setPaymentService(PaymentService paymentService) {
    this.paymentService = paymentService;
}
Spring injects dependency by calling a setter method.
You can add validation or logic inside the method.

Key Differences

Feature Field Injection Setter Injection
Injection Method Reflection Method Call
Encapsulation Breaks encapsulation Preserves encapsulation
Testing Hard Easier
Custom Logic Not possible Possible

Industry Best Practice

Constructor Injection
+ final fields
+ Lombok @RequiredArgsConstructor
@Service
@RequiredArgsConstructor
public class OrderService {

    private final PaymentService paymentService;

}
Field Injection   → Avoid
Setter Injection  → Optional dependencies
Constructor       → Recommended