Spring - Dependency Injection
Dependency Injection (DI) is the practical mechanism Spring uses to implement IoC. Instead of objects creating their own dependencies, Spring injects them at runtime. Spring supports three styles of DI: constructor injection, setter injection, and field injection.
Constructor Injection
Constructor injection provides dependencies through the constructor. This is the recommended approach because it makes dependencies explicit, supports immutability with final
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private final PaymentService paymentService;
private final InventoryService inventoryService;
// Spring automatically injects beans when there is only one constructor
public OrderService(PaymentService paymentService, InventoryService inventoryService) {
this.paymentService = paymentService;
this.inventoryService = inventoryService;
}
public void placeOrder(Order order) {
inventoryService.reserve(order);
paymentService.charge(order);
}
}
Since Spring 4.3, if a class has only one constructor, the @Autowired
Setter Injection
Setter injection uses @Autowired
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class NotificationService {
private EmailService emailService;
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
public void sendNotification(String message) {
emailService.send(message);
}
}
Field Injection
Field injection places @Autowiredfinal
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class ReportService {
@Autowired
private DataSource dataSource; // Not recommended
public Report generateReport() {
// use dataSource ...
return new Report();
}
}
Which injection style to use?
- ✅ Constructor injection: preferred for mandatory, non-null dependencies. Enables
fields and easy mocking in unit tests.final - ⚠️ Setter injection: use for optional dependencies that may change after startup.
- ❌ Field injection: avoid in production. Fine for quick prototypes only.