Spring IoC and Dependency Injection Interview Questions and Answers
Master Spring IoC and Dependency Injection with interview questions covering IoC Container, Dependency Injection, constructor injection, setter injection, field injection, @Autowired, @Qualifier, @Primary, circular dependencies, and production best practices.
Introduction
The core philosophy of the Spring Framework is Inversion of Control (IoC) and Dependency Injection (DI).
Before Spring, applications created objects manually using the new keyword. As applications grew larger, this resulted in:
- Tight coupling
- Difficult testing
- Complex object creation
- Poor maintainability
- Difficult configuration management
Spring solves these problems by allowing the IoC Container to create, configure, and inject objects automatically.
Almost every Spring module—including Spring Boot, Spring MVC, Spring Security, Spring Data JPA, and Spring Cloud—depends on IoC and DI.
IoC and DI Architecture
flowchart LR
Application --> SpringContainer
SpringContainer --> CustomerController
SpringContainer --> CustomerService
SpringContainer --> CustomerRepository
CustomerController --> CustomerService
CustomerService --> CustomerRepository
Q1. What is Inversion of Control (IoC)?
Answer
Inversion of Control (IoC) is a design principle in which the responsibility of creating and managing objects is transferred from the application to the Spring IoC Container.
Without IoC
- Application creates objects.
With IoC
- Spring creates objects.
- Spring injects dependencies.
- Spring manages lifecycle.
Benefits
- Loose coupling
- Better maintainability
- Easier testing
- Centralized object management
Q2. What is Dependency Injection (DI)?
Dependency Injection is the process of supplying required dependencies to an object instead of allowing the object to create them.
Without DI
CustomerRepository repository =
new CustomerRepository();
CustomerService service =
new CustomerService(repository);
With DI
@Service
public class CustomerService {
private final CustomerRepository repository;
public CustomerService(CustomerRepository repository) {
this.repository = repository;
}
}
Spring injects CustomerRepository automatically.
Q3. What is the relationship between IoC and DI?
- IoC is the design principle.
- DI is the implementation technique used by Spring to achieve IoC.
Relationship
flowchart TD
IoC --> SpringContainer
SpringContainer --> DependencyInjection
DependencyInjection --> ApplicationBeans
Think of IoC as the goal, and DI as the mechanism.
Q4. What are the types of Dependency Injection?
Spring supports three types.
| Type | Recommended |
|---|---|
| Constructor Injection | ✅ Yes |
| Setter Injection | Sometimes |
| Field Injection | ❌ Avoid in production |
Constructor Injection
@Service
public class PaymentService {
private final PaymentRepository repository;
public PaymentService(PaymentRepository repository) {
this.repository = repository;
}
}
Setter Injection
@Autowired
public void setRepository(
PaymentRepository repository){
}
Field Injection
@Autowired
private PaymentRepository repository;
Although simple, field injection is discouraged for production applications.
Q5. Why is Constructor Injection recommended?
Advantages
- Immutable dependencies
- Easier unit testing
- Mandatory dependencies enforced
- Better readability
- No reflection required
Spring recommends constructor injection for most enterprise applications.
Q6. What is @Autowired?
@Autowired instructs Spring to automatically inject a matching bean.
Example
@Autowired
private CustomerService
customerService;
Spring searches the IoC container for a compatible bean and injects it automatically.
From Spring 4.3 onward, if a class has a single constructor, @Autowired on the constructor is optional.
Q7. What are @Qualifier and @Primary?
When multiple beans of the same type exist, Spring cannot determine which bean to inject.
@Primary
Marks the default bean.
@Primary
@Component
class VisaPayment{
}
@Qualifier
Selects a specific bean.
@Autowired
@Qualifier("paypalPayment")
PaymentService service;
Bean Selection
flowchart LR
PaymentInterface --> VisaBean
PaymentInterface --> MasterBean
MasterBean --> Primary
VisaBean --> Qualifier
Q8. What is Circular Dependency?
A circular dependency occurs when two or more beans depend on each other.
Example
Service A
↓
Service B
↓
Service A
Circular Dependency
flowchart LR
ServiceA --> ServiceB
ServiceB --> ServiceA
Constructor-based circular dependencies result in application startup failure.
Solutions
- Redesign the dependency
- Introduce an intermediary service
- Use
@Lazyonly when absolutely necessary
Q9. What is Loose Coupling?
Loose coupling means classes depend on abstractions, not concrete implementations.
Example
interface PaymentProcessor{
}
Implementations
- Credit Card
- UPI
- PayPal
The service depends only on the interface.
Benefits
- Easier testing
- Better extensibility
- Cleaner architecture
Q10. IoC and DI Best Practices
Prefer Constructor Injection
Avoid field injection.
Depend on Interfaces
Program to abstractions.
Keep Beans Stateless
Improve scalability.
Avoid Circular Dependencies
Refactor instead of using workarounds.
Use @Qualifier Only When Needed
Use @Primary for the default implementation.
Banking Example
flowchart TD
CustomerController --> CustomerService
CustomerService --> PaymentProcessor
PaymentProcessor --> VisaProcessor
PaymentProcessor --> UpiProcessor
VisaProcessor --> BankAPI
UpiProcessor --> UpiGateway
SpringContainer --> CustomerController
SpringContainer --> CustomerService
SpringContainer --> VisaProcessor
SpringContainer --> UpiProcessor
Spring injects the appropriate implementation based on configuration.
Common Interview Questions
- What is IoC?
- What is Dependency Injection?
- IoC vs Dependency Injection?
- Types of Dependency Injection?
- Constructor vs Setter Injection?
- Why avoid Field Injection?
- What is
@Autowired? - What are
@Qualifierand@Primary? - What is Circular Dependency?
- Why is Constructor Injection recommended?
Quick Revision
| Topic | Summary |
|---|---|
| IoC | Spring manages object creation |
| Dependency Injection | Inject required dependencies |
| Constructor Injection | Recommended approach |
| Setter Injection | Optional dependencies |
| Field Injection | Avoid in production |
| @Autowired | Automatic dependency injection |
| @Qualifier | Select specific bean |
| @Primary | Default bean |
| Loose Coupling | Depend on interfaces |
| Circular Dependency | Mutual bean dependency |
Dependency Injection Lifecycle
sequenceDiagram
Application->>Spring Container: Start
Spring Container->>CustomerRepository: Create Bean
Spring Container->>CustomerService: Create Bean
Spring Container->>CustomerService: Inject Repository
Spring Container->>CustomerController: Create Bean
Spring Container->>CustomerController: Inject Service
Spring Container-->>Application: Ready
Production Example – Banking Payment Platform
A banking application supports multiple payment methods:
- Credit Card
- UPI
- Net Banking
The PaymentService depends only on the PaymentProcessor interface.
During startup:
- Spring scans all components.
- It creates beans for each payment implementation.
@Primaryidentifies the default processor.@Qualifiercan inject a specific implementation when needed.- Constructor injection ensures all required dependencies are available before the application starts.
flowchart LR
SpringContainer --> PaymentService
SpringContainer --> CreditCardProcessor
SpringContainer --> UpiProcessor
SpringContainer --> NetBankingProcessor
PaymentService --> PaymentProcessor
PaymentProcessor --> CreditCardProcessor
PaymentProcessor --> UpiProcessor
PaymentProcessor --> NetBankingProcessor
This design promotes loose coupling, simplifies testing with mock implementations, and makes it easy to introduce new payment methods without modifying existing business logic.
Key Takeaways
- Inversion of Control (IoC) transfers object creation and lifecycle management from the application to the Spring Container.
- Dependency Injection (DI) is the mechanism Spring uses to implement IoC by automatically supplying required dependencies.
- Constructor Injection is the recommended approach because it supports immutability, mandatory dependencies, and easier testing.
- Setter Injection is suitable for optional dependencies, while Field Injection should generally be avoided in production code.
@Autowiredautomatically injects matching beans from the Spring IoC Container.- Use
@Primaryto define a default implementation and@Qualifierwhen multiple implementations of the same interface exist. - Avoid circular dependencies through better design rather than relying on
@Lazy. - Following IoC and DI best practices results in modular, testable, maintainable, and enterprise-ready Spring applications.