Короткий ответ
IoC (Inversion of Control) — принцип, по которому управление созданием и жизненным циклом объектов передаётся контейнеру. DI (Dependency Injection) — паттерн внедрения зависимостей и один из способов реализации IoC: контейнер сам предоставляет объекту его зависимости.
Как это работает подробнее
В Spring инверсию контроля реализует IoC-контейнер — базовый BeanFactory или расширенный ApplicationContext. Он создаёт бины, связывает их и управляет их временем жизни, поэтому приложение не вызывает new, а лишь описывает нужные ему объекты. Именно поэтому подход называется инверсией контроля: контроль над созданием объектов переходит от кода приложения к контейнеру.
- IoC шире, чем DI: IoC — общий принцип инверсии управления, а DI — конкретная техника, один из способов его реализации.
- Способы DI: внедрение через конструктор, через сеттер и напрямую в поле (field injection).
- Для запоминания: «Spring создаёт бин» — это IoC, а «Spring внедряет один бин в другой» — это DI.
Пример кода
UserService.java
@Service
public class UserService {
private final UserRepository repository;
public UserService(UserRepository repository) {
this.repository = repository;
}
}Что использовать на практике
- Предпочитайте внедрение через конструктор: объект создаётся полностью инициализированным и неизменяемым, его легко тестировать, передавая моки.
- Для опциональных зависимостей уместна сеттерная инъекция.
- Инъекцию в поле через
@Autowiredв продакшен-коде лучше избегать.