Если есть @Qualifier и @Primary, какой способ инжекции применяется в Spring
Что проверяют
Знаете ли вы приоритет разрешения бинов. Вопрос точечный, и правильный ответ короткий, но за ним обычно идёт продолжение про то, как вообще выбирается кандидат.
Как отвечать
Побеждает @Qualifier. Он указывает конкретный бин в точке внедрения, а @Primary это лишь значение по умолчанию на случай, когда явного указания нет.
Полный порядок разрешения, если кандидатов несколько, выглядит так:
- сначала отбираются бины подходящего типа;
- если в точке внедрения есть
@Qualifier, выбирается бин с этим именем или квалификатором; - если квалификатора нет, но один из кандидатов помечен
@Primary, берётся он; - если и этого нет, Spring сравнивает имя переменной с именами бинов;
- ничего не подошло или подошло несколько, приложение падает при старте с
NoUniqueBeanDefinitionException.
@Bean @Primary NotificationSender email() { ... }
@Bean("sms") NotificationSender sms() { ... }
// сюда придёт sms, несмотря на @Primary у email
public OrderService(@Qualifier("sms") NotificationSender sender) { ... }Полезно добавить: вместо строковых имён надёжнее собственная аннотация-квалификатор, она проверяется компилятором. А если нужны все реализации сразу, Spring умеет внедрить List<NotificationSender> или Map<String, NotificationSender> с именами в ключах, и тогда выбор делается уже в коде.
Где спотыкаются
Считают, что @Primary сильнее и перебивает всё.
Ставят @Primary сразу нескольким бинам одного типа и получают падение на старте.
Полагаются на совпадение имени переменной с именем бина: работает, но ломается при первом же переименовании.