junior
Что такое Dependency Injection?
Dependency Injection (DI) – паттерн, при котором объект получает свои зависимости извне, а не создаёт их сам. Реализует принцип Dependency Inversion (D из SOLID).
Аналогия из жизни: DI – как заказ еды в ресторане. Вы не идёте на кухню сами (не создаёте зависимости), а официант (контейнер) приносит вам блюдо (зависимость) за столик.
Пример
// БЕЗ DI -- жёсткая связность
class OrderService {
private final OrderRepository repo = new PostgresOrderRepository(); // жёсткая связь
private final EmailService email = new SmtpEmailService(); // жёсткая связь
}
// С DI -- слабая связность
class OrderService {
private final OrderRepository repo;
private final EmailService email;
// Зависимости внедряются через конструктор (рекомендуемый способ)
OrderService(OrderRepository repo, EmailService email) {
this.repo = repo;
this.email = email;
}
}
Три способа внедрения в Spring
| Способ | Рекомендуется | Поля final | Тестируемость | Пример |
|---|---|---|---|---|
| Конструктор | Да | Да | Легко (new Service(mock)) |
OrderService(OrderRepository repo) |
| Сеттер | Иногда | Нет | Средне | @Autowired void setRepo(...) |
| Поле | Нет | Нет | Только через reflection | @Autowired private OrderRepository repo |
Примеры трёх способов
// 1. Через конструктор (РЕКОМЕНДУЕТСЯ)
@Service
class OrderService {
private final OrderRepository repo;
OrderService(OrderRepository repo) { this.repo = repo; }
}
// 2. Через сеттер
@Service
class OrderService {
private OrderRepository repo;
@Autowired
void setRepo(OrderRepository repo) { this.repo = repo; }
}
// 3. Через поле (НЕ РЕКОМЕНДУЕТСЯ -- затрудняет тестирование)
@Service
class OrderService {
@Autowired
private OrderRepository repo;
}
Важное
- DI = реализация Dependency Inversion Principle (D из SOLID)
- Конструктор – лучший способ: поля final, объект полностью инициализирован, легко тестировать
- IoC-контейнер (Spring) – автоматизирует DI, управляя созданием и связыванием объектов
Частые ошибки
- Field injection – невозможно создать объект без рефлексии;
new OrderService()не скомпилируется - Циклические зависимости – A зависит от B, B от A; признак плохого дизайна
newвнутри сервиса для зависимостей – нарушает DI; используйте фабрику или Provider
Как используется в 2026
- Spring IoC – стандартный DI-контейнер в Java-экосистеме
- Constructor injection – единственный рекомендуемый способ
На собеседовании: объясните разницу между DI и IoC (DI – конкретный паттерн, IoC – общий принцип, DI – один из способов реализации IoC). Частая ошибка – использовать field injection в примерах и не знать, почему constructor injection лучше.