What is Inversion of Control (IoC), and how does Spring's container implement it?
Quick Answer
Inversion of Control means an object's dependencies are supplied to it from the outside rather than the object creating or looking them up itself, inverting the traditional flow where code controls its own dependency creation. Spring implements this via its IoC container (the ApplicationContext), which reads bean definitions (from annotations or XML), instantiates objects, wires their dependencies together, and manages their lifecycle — so application code just declares what it needs, and the container provides it.
Detailed Answer
In traditional procedural code, an object typically creates its own collaborators directly:
class OrderService {
private PaymentGateway gateway = new StripeGateway(); // OrderService controls its own dependency
}
Inversion of Control flips this: the object declares what it needs, and something external supplies it — control over creating and wiring dependencies moves out of the object and into a container:
class OrderService {
private final PaymentGateway gateway;
OrderService(PaymentGateway gateway) { this.gateway = gateway; } // supplied from outside
}
Spring's IoC container (most commonly accessed via ApplicationContext) is the component that actually performs this inversion at runtime:
- It scans for bean definitions — via component scanning (
@Component,@Service, ...),@Beanmethods in@Configurationclasses, or (historically) XML. - It instantiates the beans, resolving each one's declared dependencies (constructor parameters,
@Autowiredfields/setters) by looking them up among other managed beans. - It wires everything together and manages each bean's full lifecycle (initialization callbacks, scope, destruction).
@Service
class OrderService {
private final PaymentGateway gateway;
@Autowired // Spring resolves and injects this automatically
OrderService(PaymentGateway gateway) { this.gateway = gateway; }
}
The practical benefit: OrderService never mentions a concrete class (StripeGateway), only the PaymentGateway abstraction — the container decides which implementation to plug in, which is what makes it trivial to swap implementations (for tests, different environments, or different providers) without touching OrderService itself.