IoC и Dependency Injection
Зависимость не обязательно создавать самому
Представь сервис, который отправляет уведомление. Ему нужен объект для отправки сообщения.
Самый прямой вариант — создать его внутри сервиса через new.
Но тогда сервис сам решает, какую реализацию использовать, и оказывается жёстко с ней связан.
class NotificationService {
private final MessageSender sender;
NotificationService(MessageSender sender) {
this.sender = sender;
}
void notifyUser(String message) {
sender.send(message);
}
}
Здесь NotificationService не создаёт отправителя.
Он просто объявляет: «для работы мне нужен MessageSender».
Готовый объект передаётся снаружи через конструктор. Это и есть Dependency Injection —
внедрение зависимости.
Где здесь IoC
Inversion of Control — идея шире. Код класса больше не контролирует весь процесс создания и связывания объектов. Эту часть управления получает внешний механизм — в Spring это контейнер. Он знает, какие объекты доступны, какие зависимости им нужны и как собрать из них готовую систему.
DI — один из главных способов реализовать IoC. Вместо цепочки из десятков ручных
new контейнер создаёт объекты сам и передаёт им нужные зависимости.
Что меняется в мышлении
В Spring-приложении полезно задавать не вопрос «где мне создать этот объект?», а вопрос «какой объект мне нужен для работы?». Создание и связывание постепенно переносится из бизнес-кода в конфигурацию контейнера. На следующих страницах мы увидим, где этот контейнер живёт и какими объектами он управляет.