Constructor injection provides dependencies through the constructor. This is the recommended approach because it makes dependencies explicit, supports immutability with final fields, and makes the class easy to unit-test.
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 annotation is optional — Spring uses it automatically.
Setter injection uses @Autowired on a setter method. This is useful for optional dependencies or when you need to allow the dependency to be changed after object creation.
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 places @Autowired directly on a field. Although concise, it is not recommended for production code — it hides dependencies, makes unit testing harder, and cannot be used with final fields.
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();
}
}
- ✅ Constructor injection — preferred for mandatory, non-null dependencies. Enables final fields and easy mocking in unit tests.
- ⚠️ Setter injection — use for optional dependencies that may change after startup.
- ❌ Field injection — avoid in production. Fine for quick prototypes only.