Gymterview
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 лучше.