Вопрос проверяет знание основных подходов Dependency Injection в Spring и умение оценивать их плюсы и минусы.
В Spring существуют constructor-injection, setter-injection и field-injection. На практике чаще всего используют внедрение через конструктор. Оно делает зависимости явными и упрощает тестирование. Setter-injection применяется для необязательных зависимостей. Field-injection считается наименее предпочтительным.
Spring поддерживает несколько способов внедрения зависимостей, каждый из которых имеет свои сценарии применения.
Dependency Injection — это принцип, при котором объект получает зависимости извне, а не создаёт их сам.
Перед перечислением важно отметить, что все способы работают через контейнер Spring, различается только момент и форма передачи зависимости.
Самый рекомендуемый способ.
@Component
class OrderService {
private final PaymentService paymentService;
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
Плюсы:
Все зависимости обязательны и явны
Объект всегда в корректном состоянии
Удобно писать unit-тесты
Хорошо сочетается с final
Минусы:
Конструктор может разрастаться при большом числе зависимостей
Используется реже и в специфических случаях.
@Component
class ReportService {
private Formatter formatter;
@Autowired
void setFormatter(Formatter formatter) {
this.formatter = formatter;
}
}
Плюсы:
Подходит для необязательных зависимостей
Можно менять зависимость после создания бина
Минусы:
Объект может быть создан в неполном состоянии
Самый простой, но наименее рекомендуемый способ.
@Component
class UserService {
@Autowired
private UserRepository repository;
}
Минусы:
Зависимости скрыты
Сложно тестировать без Spring
Нельзя использовать final
Нарушает принцип явности
Лучший выбор по умолчанию — constructor-injection. Остальные способы стоит использовать только при наличии чёткой причины.