A service uses field injection with `@Autowired` and a unit test does `new OrderService()`. What happens and what is the better design?
basicThe test compiles but every injected field is null, so the first call throws NullPointerException. Constructor injection makes dependencies explicit, lets fields be final, and makes the object impossible to create in an invalid state.
@Service
public class OrderService {
private final PaymentClient payments;
private final OrderRepository repo;
public OrderService(PaymentClient payments, OrderRepository repo) {
this.payments = payments;
this.repo = repo;
}
}With a single constructor, @Autowired is optional (since Spring 4.3). In the test you pass mocks directly, with no Spring context.
- Can field injection fields be
final? No, reflection sets them after construction, so they cannot be final. - When is setter injection still appropriate? For genuinely optional or re-configurable dependencies.