Card 01/ 07

ConceptDifficulty: Intermediate1 min

Why Constructor Injection Is the Default

RideService below compiles, runs, and cannot be unit-tested without starting a whole Spring container — because there is no constructor a test could call directly. Every dependency arrives through field injection, after the fact.

java
@Service
class RideService {
    @Autowired private RideRepository repository;
    @Autowired private PricingClient pricingClient;
    @Autowired private NotificationSender notifier;
    @Autowired private AuditLog auditLog;
    // and two more...
}

Field and constructor injection wire exactly the same objects — that part is not in question. What differs is what happens without a container in the room: a class wired by constructor cannot exist half-built, because Java itself refuses to construct it without the arguments; new RideService() with no arguments does not compile. A class wired by field injection instantiates happily with every field left null, and only fails later, wherever the missing dependency first gets used.

That is the actual argument for constructor injection: the class cannot be in an invalid, half-wired state, and every dependency it has is visible in one place — the constructor's parameter list — rather than scattered across annotated fields.