IoC and Dependency Injection
A dependency does not have to be created by the object itself
Imagine a service that sends a notification. It needs an object that can send a message.
The most direct option is to create it inside the service with new.
But then the service decides which implementation to use and becomes tightly coupled to it.
class NotificationService {
private final MessageSender sender;
NotificationService(MessageSender sender) {
this.sender = sender;
}
void notifyUser(String message) {
sender.send(message);
}
}
Here, NotificationService does not create the sender.
It simply declares: “I need a MessageSender to work.”
A ready-to-use object is passed from the outside through the constructor. This is Dependency Injection —
injecting a dependency.
Where IoC fits in
Inversion of Control is a broader idea. The class no longer controls the whole process of creating and connecting objects. An external mechanism receives that part of the control — in Spring, that is the container. It knows which objects are available, which dependencies they need, and how to assemble a working system from them.
DI is one of the main ways to implement IoC. Instead of a chain of dozens of manual
new calls, the container creates objects itself and provides the dependencies they need.
What changes in the way you think
In a Spring application, it is useful to ask not “where should I create this object?” but “which object do I need to do the job?”. Creation and wiring gradually move out of business code and into container configuration. On the next pages, we will see where this container lives and which objects it manages.