What is Dependency Injection?
Understand dependency injection: constructor injection, inversion of control, testability, and a Java code example.
Expected Interview Answer
Dependency injection is a technique where an object receives its dependencies from an external source rather than creating them itself, typically via constructor, setter, or field injection.
Instead of a class instantiating the services it needs internally, those services are constructed elsewhere and passed in, which means the class depends on an interface rather than a concrete implementation it controls. This decouples components, making them easier to test in isolation with mock or stub dependencies, and easier to reconfigure without touching the consuming class. Frameworks like Spring automate this via an IoC (Inversion of Control) container that wires dependencies together at startup. The core idea is inversion of control: the framework or caller controls object wiring, not the object itself.
- Enables easy unit testing with mocks or stubs
- Decouples classes from concrete implementations
- Centralizes configuration and wiring in one place
- Supports swapping implementations without code changes
AI Mentor Explanation
A batter doesn’t manufacture their own bat in the dressing room — the kit manager hands them a bat that meets spec before they walk out to play. The batter just needs "a legal bat," not the specific brand, and the kit manager decides which one to supply. Dependency injection works the same way: a class doesn’t construct its own dependency, an external party supplies one meeting the required interface.
Step-by-Step Explanation
Step 1
Define the dependency as an interface
The consuming class depends on an abstraction, not a concrete implementation.
Step 2
Accept the dependency externally
Add a constructor parameter (or setter) for the interface type.
Step 3
Wire it up outside the class
A caller, factory, or IoC container constructs the concrete implementation and passes it in.
Step 4
Swap implementations freely
Tests inject mocks; production wiring injects real implementations, with zero changes to the consumer.
What Interviewer Expects
- Explaining constructor injection versus setter/field injection
- Connecting DI to the inversion-of-control principle
- Why DI makes unit testing with mocks straightforward
- Awareness of IoC containers (Spring, etc.) automating wiring
Common Mistakes
- Confusing dependency injection with the Dependency Inversion Principle (related but distinct)
- Constructing dependencies inside the class and calling it DI anyway
- Overusing field injection, which hides required dependencies
- Not realizing DI enables mocking in unit tests
Best Answer (HR Friendly)
“Dependency injection means a class doesn’t build the tools it needs itself — instead those tools are handed to it from outside, usually through the constructor, which makes the class easier to test and swap implementations without rewriting it.”
Code Example
interface PaymentGateway {
boolean charge(double amount);
}
class StripeGateway implements PaymentGateway {
public boolean charge(double amount) { return true; }
}
class OrderService {
private final PaymentGateway gateway;
// Dependency is injected, not constructed internally
OrderService(PaymentGateway gateway) {
this.gateway = gateway;
}
boolean checkout(double amount) {
return gateway.charge(amount);
}
}
// Wiring happens outside OrderService, e.g. in tests a mock is injected instead
OrderService service = new OrderService(new StripeGateway());
service.checkout(49.99);Follow-up Questions
- What is the difference between constructor and setter injection?
- How does dependency injection relate to the Dependency Inversion Principle?
- What does an IoC container do?
- How does DI improve unit testability?
MCQ Practice
1. In dependency injection, who is responsible for constructing a class’s dependencies?
DI moves construction responsibility outside the consuming class to an external supplier.
2. A key benefit of dependency injection is?
Because dependencies are interfaces supplied externally, tests can inject mock implementations.
3. What principle underlies dependency injection?
Control over object wiring is inverted from the class itself to an external caller or container.
Flash Cards
What is dependency injection? — Supplying a class’s dependencies from outside rather than it constructing them.
Most common injection style? — Constructor injection.
Underlying principle? — Inversion of control.
Why does DI help testing? — Mocks or stubs can be injected in place of real implementations.