What is Dependency Injection in Spring, and why is it important?
Updated Feb 20, 2026
Short answer
Dependency Injection is a design pattern where Spring creates and provides an object's dependencies instead of the object creating them itself. It reduces coupling, improves testability, and makes applications easier to maintain because classes focus on their responsibilities rather than object creation.
Deep explanation
What Dependency Injection means
In traditional code, a class often creates the objects it needs:
class OrderService { private PaymentService paymentService = new PaymentService();}The OrderService is tightly coupled to PaymentService. If the payment logic changes or you want to use a fake payment service during testing, the class must be modified.
With Dependency Injection, the responsibility of creating and connecting objects moves to the Spring container. The class simply declares what it needs, and Spring supplies it.
The key idea: objects receive their dependencies from outside instead of creating them internally.
How Spring performs Dependency Injection
Spring uses an IoC (Inversion of Control) container to manage application objects called beans. A bean is an object created, configured, and managed by Spring.
Common ways to inject dependencies:
| Injection type | How it works | Recommendation |
|---|---|---|
| Constructor injection | Dependency is provided through a constructor | Preferred approach |
| Setter injection | Dependency is provided through a setter method | Useful for optional dependencies |
| Field injection | Dependency is placed directly on a field | Generally avoided |
A typical example uses constructor injection:
@Serviceclass OrderService {
private final PaymentService paymentService;
OrderService(PaymentService paymentService) { this.paymentService = paymentService; }
void placeOrder() { paymentService.processPayment(); }}Here, OrderService does not know how PaymentService is created. It only depends on the PaymentService contract.
Dependency flow in Spring
Why Dependency Injection matters
Dependency Injection makes code loosely coupled, which means classes depend on abstractions rather than concrete implementations.
This provides several benefits:
- Better testing: A real database service can be replaced with a mock implementation during unit tests.
- Easier maintenance: Changing one implementation does not require rewriting every class that uses it.
- Reusable components: Services can be shared and configured centrally.
- Cleaner design: Classes follow the Single Responsibility Principle by avoiding object creation logic.
⚠️ A good rule of thumb: a class should describe what it needs, not how to build what it needs.
Dependency Injection vs creating objects manually
| Approach | Object creation | Coupling |
|---|---|---|
Manual creation with new | Class controls creation | Higher |
| Dependency Injection | Container controls creation | Lower |
The interviewer is usually checking whether you understand that `Spring` manages object relationships, not just that it automatically creates objects.
Real-world example
Imagine an online shopping application with an OrderService. Today it uses StripePaymentService, but tomorrow the business may switch to another payment provider.
With Dependency Injection, OrderService depends on the PaymentService interface, not a specific provider:
interface PaymentService { void processPayment();}
@Serviceclass OrderService { private final PaymentService paymentService;
OrderService(PaymentService paymentService) { this.paymentService = paymentService; }}Spring can inject the correct implementation based on configuration. The order logic remains unchanged, even when payment providers change.
Common mistakes
- * **Field injection** - Using `@Autowired` directly on fields makes testing harder and hides dependencies
- prefer constructor injection.
- * **Confusing DI with object creation** - Dependency Injection does not remove objects
- it moves creation and wiring responsibility to `Spring`.
- * **Injecting concrete classes everywhere** - Depending on interfaces or abstractions usually creates more flexible designs.
- * **Overusing dependencies** - A class with too many injected services may have too many responsibilities
- consider splitting it.
Follow-up questions
- What is the difference between Dependency Injection and Inversion of Control?
- Why is constructor injection preferred over field injection in Spring?
- What happens if Spring finds multiple beans of the same type?
- What are Spring beans?