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

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

Ответ

В Spring Framework есть три основных способа внедрения зависимостей, которые могут использоваться аннотацией @Autowired или через Java-конфигурацию.

1. Внедрение через конструктор (Constructor Injection) **

Самый предпочтительный способ. Зависимости передаются через параметры конструктора. Делает класс неизменяемым (immutable), зависимости явные и обязательные.

@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired // Необязательно в Spring 4.3+ для единственного конструктора
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

2. Внедрение через сеттер (Setter Injection)

Зависимости устанавливаются через setter-методы. Полезно для опциональных зависимостей или когда нужна возможность их изменения после создания объекта.

@Service
public class PaymentService {
    private NotificationService notificationService;

    @Autowired
    public void setNotificationService(NotificationService notificationService) {
        this.notificationService = notificationService;
    }
}

3. Внедрение через поле (Field Injection) **

Зависимость инжектируется напрямую в поле класса. Не рекомендуется для production-кода, так как скрывает зависимости, усложняет тестирование (требует Spring-контекста или рефлексии) и нарушает принцип инкапсуляции.

@Service
public class OrderService {
    @Autowired // Внедрение напрямую в поле
    private OrderRepository orderRepository;
}

Рекомендации:

  • Используйте Constructor Injection по умолчанию для обязательных зависимостей.
  • Setter Injection подходит для опциональных зависимостей или конфигураций, которые могут меняться.
  • Избегайте Field Injection в новом коде.
  • Внедрение может также настраиваться через Java-based конфигурацию (@Bean методы) или XML (в legacy-проектах).