Ответ
Внедрение зависимостей через конструктор (Constructor Injection) — это предпочтительный способ в Spring, так как он обеспечивает неизменяемость (immutability) и гарантирует, что бин будет создан только в полностью инициализированном состоянии.
Принцип работы:
- Spring анализирует конструктор класса (начиная с версии 4.3, для единственного конструктора аннотация
@Autowiredне обязательна). - Для каждого параметра конструктора контейнер ищет подходящий бин по типу (и, при необходимости, по имени
@Qualifier). - Создает экземпляр класса, передавая найденные бины в качестве аргументов конструктора.
Пример:
@Service
public class OrderService {
private final PaymentProcessor paymentProcessor;
private final NotificationService notificationService;
// Spring автоматически внедрит зависимости
public OrderService(PaymentProcessor paymentProcessor,
NotificationService notificationService) {
this.paymentProcessor = paymentProcessor;
this.notificationService = notificationService;
}
}
Ключевые преимущества:
- Неизменяемость: Поля можно объявить как
final, что гарантирует их инициализацию только при создании объекта. - Тестируемость: Зависимости явно передаются, что упрощает создание объекта в unit-тестах с помощью
new. - Ясность контракта: Класс четко объявляет все необходимые для его работы зависимости.
- Избегание циклических зависимостей: Spring обнаруживает циклические зависимости при внедрении через конструктор на этапе создания контекста приложения.
Разрешение неоднозначности: Если есть несколько бинов одного типа, необходимо использовать @Qualifier:
public OrderService(@Qualifier("payPalProcessor") PaymentProcessor processor) {
this.paymentProcessor = processor;
}