Evaluate where dependency injection improves Java systems and where it becomes unnecessary indirection.
DI use case: A situation where externalizing collaborator selection improves ownership, substitution, or lifecycle clarity.
Dependency injection helps most where infrastructure choices and domain behavior should evolve separately.
Dependency injection is especially useful for:
Example:
1public final class PaymentService {
2 private final PaymentGateway gateway;
3
4 public PaymentService(PaymentGateway gateway) {
5 this.gateway = gateway;
6 }
7}
The service can use a real gateway in production and a fake or stubbed one in tests.
DI is a weak trade when:
Not every new call is an architectural problem.
Dependency injection makes layered behavior easier:
1PaymentGateway gateway = new MetricsPaymentGateway(
2 new RetryingPaymentGateway(realGateway));
The service still depends on the PaymentGateway abstraction. Wiring decides which concrete composition to supply.
When reviewing DI use cases, ask:
The best DI use cases have a clear reason for separating choice of collaborator from use of collaborator.