Как реализуется Dependency Injection (DI) в Spring Boot?

«Как реализуется Dependency Injection (DI) в Spring Boot?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Spring Boot реализует Dependency Injection (DI) через механизм Inversion of Control (IoC) контейнера, который автоматически управляет жизненным циклом объектов (бинов) и их зависимостями.

Основные механизмы:

  1. Объявление бинов:

    • Стереотипные аннотации: @Component, @Service, @Repository, @Controller. Spring сканирует класспат и регистрирует помеченные классы как бины.
    • Явное объявление: В классах, помеченных @Configuration, методы с @Bean возвращают экземпляр бина.
  2. Внедрение зависимостей:

    • Через конструктор (рекомендуется): Наиболее предпочтительный способ, обеспечивает неизменяемость и обязательность зависимости.

      @Service
      public class UserService {
          private final UserRepository userRepo;
      
          @Autowired // Необязательно с Spring 4.3+
          public UserService(UserRepository userRepo) {
              this.userRepo = userRepo;
          }
      }
    • Через поле: Используется @Autowired над полем. Менее тестируемо и скрывает обязательные зависимости.
    • Через сеттер: Аналогично полю, но с аннотацией над setter-методом.

Как это работает в Spring Boot:

  • Аннотация @SpringBootApplication включает автоматическое сканирование компонентов и автоконфигурацию.
  • Контейнер IoC создает граф зависимостей, разрешая их на этапе запуска приложения.
  • Для устранения неоднозначности (несколько бинов одного типа) используются @Qualifier или @Primary.