Constructor injection
Wire dependencies the way the Spring team recommends, and see why field injection loses.
Open this lesson in the learning hubKey points
- Ask for collaborators as constructor parameters. Spring supplies a matching bean for each one.
- A class with a single constructor needs no
@Autowiredat all. Spring infers it. - Fields can then be
private final— the object is fully built and immutable from birth. - Field injection (
@Autowiredon a field) hides dependencies and cannot be set in a plain unit test. - A long constructor is honest feedback: the class has too many jobs. Split it.
- For an optional dependency use
Optional<T>or@Nullablerather than a second constructor.
Example
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private final OrderRepository orders;
private final PaymentClient payments;
// Single constructor -> @Autowired is optional and usually omitted.
public OrderService(OrderRepository orders, PaymentClient payments) {
this.orders = orders;
this.payments = payments;
}
public Order place(Order order) {
payments.charge(order.total());
return orders.save(order);
}
}
// In a unit test there is no Spring at all:
// new OrderService(fakeRepo, fakePayments)
Constructor injection gives you final fields, honest dependencies and testable classes.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.