Какой способ внедрения зависимостей (Dependency Injection) в Spring является лучшим и почему?

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

Ответ

Внедрение через конструктор (Constructor Injection) — это рекомендуемый best practice в Spring.

Пример реализации:

@Service
public class UserService {
    private final UserRepository userRepository;
    // Начиная с Spring 4.3, аннотация @Autowired для конструктора с одним параметром не обязательна
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

Почему это лучший способ:

  1. Неизменяемость (Immutability): Поля можно объявить как final, гарантируя их инициализацию только один раз.
  2. Явность зависимостей: Все зависимости видны в сигнатуре конструктора, что упрощает понимание класса.
  3. Упрощение тестирования: Зависимости легко передать в конструктор при unit-тестировании без необходимости Spring-контекста.
  4. Безопасность от NPE: Объект не может быть создан в неполностью инициализированном состоянии.

Альтернативные (менее предпочтительные) способы:

  • Внедрение через поле (Field Injection): Не рекомендуется из-за сложности тестирования и скрытых зависимостей.
  • Внедрение через сеттер (Setter Injection): Подходит для опциональных зависимостей, которые могут меняться в runtime.