Constructor Injection
Constructor injection supplies a class with its required dependencies through its constructor, making those dependencies explicit. It is a common form of Dependency Injection in Java backend applications.
A class uses constructor injection when its dependencies are received as constructor parameters instead of being created internally. The class then stores those dependencies and uses them when performing its work.
This separates object construction from business logic. For example, a `UserService` can receive a `UserRepository` rather than calling `new UserRepository()` itself.
Constructor injection also makes required dependencies visible in the class's constructor. If an object can only function when a dependency exists, requiring that dependency during construction helps prevent partially initialized objects.
In Java applications, a dependency-injection framework such as Spring can create the objects and supply their dependencies automatically. The underlying principle does not require a framework; dependencies can also be passed manually by application code.
Key points
- Dependencies are passed through the constructor.
- Required dependencies are explicit at object creation.
- The class does not need to construct its own collaborators.
- Constructor injection improves testability by allowing test doubles to be supplied.
- Dependency Injection can be used with or without a framework.
Interview questions
Does constructor injection require Spring?
No. Constructor injection is a design technique rather than a Spring-specific feature. In plain Java, application code can create a dependency and pass it into another object's constructor manually. Spring can automate that object creation and dependency wiring, but the underlying technique works independently of the framework.
What is constructor injection?
Constructor injection is a Dependency Injection technique where a class receives its dependencies as constructor arguments. The class stores those dependencies and uses them instead of constructing them internally. This makes required dependencies explicit when the object is created. It also makes the class easier to instantiate in a unit test.
Why would you prefer constructor injection for required dependencies?
A required dependency must exist for the object to work correctly, so requiring it during construction makes that requirement explicit. It reduces the chance of creating an incompletely initialized object. Constructor injection also works naturally with `final` fields and ordinary Java code. Tests can provide mocks or other test implementations directly through the constructor.
How does constructor injection improve unit testing?
A test can construct the class directly and pass a mock, stub, or fake dependency into its constructor. This avoids requiring the dependency's real implementation or a framework-managed object. The test therefore controls the collaborator used by the class. That makes isolated unit tests simpler and more predictable.