The full picture
@Service
public class OrderService {
private final OrderRepository repo; // final — visible in any thread
private final PaymentPort payments; // safely after construction
// Single constructor: @Autowired not even needed (Spring 4.3+)
public OrderService(OrderRepository repo, PaymentPort payments) {
this.repo = repo;
this.payments = payments;
}
}
// Unit test: new OrderService(fakeRepo, fakePayments) — no Spring, no reflection.| Criterion | Constructor | Setter | Field |
|---|---|---|---|
| Immutability / final fields | ✅ | ❌ | ❌ |
| Honest API (deps visible) | ✅ | partly | ❌ hidden |
| Testable without container | ✅ plain new | ✅ awkward | ❌ reflection |
| Fails fast on missing dep | ✅ at construction | ❌ NPE later | ❌ NPE later |
| Circular dependency behavior | fails at startup (good!) | may 'work' silently | may 'work' silently |