Назад к вопросам
Junior
70
questionbank

Какие виды внедрения зависимостей вы знаете?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Есть три основных вида:

  1. Внедрение через поле (Field Injection): Зависимость внедряется напрямую в поле класса с помощью аннотации (например, @Autowired в Spring). Простой в использовании, но затрудняет модульное тестирование и нарушает принцип единой ответственности, скрывая зависимости.

    // Пример Field Injection
    public class MyService {
        // Зависимость внедряется напрямую в поле
        @Autowired
        private MyRepository repository;
    
        public void doSomething() {
            repository.getData();
        }
    }
    
  2. Внедрение через сеттер (Setter Injection): Зависимость внедряется через публичный метод-сеттер. Позволяет опционально иметь зависимость (необязательно устанавливать), удобно для изменения зависимостей во время выполнения (хотя и редко используется). Не создает обязательную зависимость при создании объекта.

    // Пример Setter Injection
    public class MyService {
        private MyRepository repository;
    
        // Зависимость внедряется через сеттер
        @Autowired
        public void setRepository(MyRepository repository) {
            this.repository = repository;
        }
    
        public void doSomething() {
            repository.getData();
        }
    }
    
  3. Внедрение через конструктор (Constructor Injection): Зависимость внедряется через аргумент конструктора. Является предпочтительным, так как обеспечивает обязательность зависимости (без нее объект не может быть создан), упрощает модульное тестирование (легко передать мок-объекты) и ясно декларирует потребности класса. Делает объекты неизменяемыми после создания, если поля final.

    // Пример Constructor Injection
    public class MyService {
        private final MyRepository repository; // Поле может быть final
    
        // Зависимость внедряется через конструктор
        @Autowired // В новых версиях Spring можно опустить аннотацию @Autowired для единственного конструктора
        public MyService(MyRepository repository) {
            this.repository = repository;
        }
    
        public void doSomething() {
            repository.getData();
        }
    }
    

Сравнительная таблица:

Вид внедрения Обязательность зависимости Простота использования Тестируемость Неизменяемость
Через поле Опционально (скрыто) Высокая Низкая Нет
Через сеттер Опционально Средняя Средняя Нет
Через конструктор Обязательно Средняя Высокая Возможна

В большинстве случаев рекомендуется использовать внедрение через конструктор.