Card 01/ 07
Constructor Injection: Why It Is Spring's Default
A class wired through its constructor cannot exist half-built, and every dependency is listed in one place.
Constructor injection means a class receives its dependencies as constructor parameters, and the container supplies them when it creates the bean. Field injection means the container writes them into fields marked @Autowired after the object already exists. Both wire the same objects, and constructor injection is the one to use by default.
The RideService below compiles and runs inside Spring, but a unit test cannot create it without starting a whole Spring container, because there is no constructor a test could call with its dependencies. Every dependency arrives through a field, after the object has been created:
@Service
class RideService {
@Autowired private RideRepository repository;
@Autowired private PricingClient pricingClient;
@Autowired private NotificationSender notifier;
@Autowired private AuditLog auditLog;
// and two more...
}What differs is what happens without a container. A class wired through its constructor cannot exist half-built, because Java will not construct it without the arguments: new RideService() with no arguments does not compile. A class wired through fields can be created with every field left null, and it only fails later, wherever a missing dependency is first used.
The constructor also makes the class's needs visible. Six dependencies become six parameters in one list, which a reader sees at once and a test can supply one by one with new; spread over annotated fields, the same six are easy to overlook.
So constructor injection makes a half-wired object impossible, and it puts every dependency in one place where both readers and tests can find it.
← → move through sections and cards