Ответ
@Primary и @Qualifier — это два механизма разрешения неоднозначностей (ambiguity) при внедрении зависимостей, когда Spring находит несколько бинов, подходящих по типу.
@Primary указывает предпочтительный (primary) бин.
- Когда Spring видит несколько кандидатов одного типа, он выберет тот, который помечен
@Primary. - Это декларативный и глобальный способ указать бин по умолчанию.
@Qualifier позволяет явно указать имя (qualifier) конкретного бина.
- Вы используете
@Qualifierвместе с@Autowiredдля точного выбора. - Это императивный и локальный способ, дающий больше контроля в точке инъекции.
Пример:
// Два бина одного типа
@Component("smsService") // Имя бина - "smsService"
class SmsService implements NotificationService { /*...*/ }
@Component
@Primary // Этот бин будет выбран по умолчанию
class EmailService implements NotificationService { /*...*/ }
// Класс, использующий внедрение
@Component
public class MyClient {
// Spring выберет EmailService, так как он @Primary
@Autowired
private NotificationService defaultService;
// Явно запрашиваем бин с именем "smsService"
@Autowired
@Qualifier("smsService")
private NotificationService specificService;
}
| Ключевые отличия: | Критерий | @Primary | @Qualifier |
|---|---|---|---|
| Стратегия | Объявление бина по умолчанию | Явное указание в точке инъекции | |
| Уровень | На уровне определения бина (@Component, @Bean) |
На уровне инъекции (@Autowired) |
|
| Гибкость | Менее гибкий (один бин по умолчанию) | Более гибкий (разный выбор в разных местах) | |
| Приоритет | Ниже: @Qualifier всегда побеждает @Primary**. | **Выше**: Если указан@Qualifier,@Primary` игнорируется. |
Практическое правило: Используйте @Primary для обозначения наиболее распространенной реализации. Используйте @Qualifier, когда в разных частях приложения нужны разные реализации одного интерфейса.
Ответ 18+ 🔞
Давай разберём эту дичь с @Primary и @Qualifier, а то у меня уже глаза на лоб лезут, как у Герасима, когда он Муму топил. Весринг, сука, находит два бина одного типа и впадает в ступор, как будто впервые видит хуй в пальто.
Вот смотри, представь, у тебя есть интерфейс Уведомлятор. А реализаций — две: СМС-шляпа и Имейл-говно. Весринг смотрит на это и говорит: «Ёпта, а какую из двух пизд я тебе воткнуть?». Вот тут-то и начинается цирк.
@Primary — это как поставить на одну из этих пизд табличку «ОФИЦИАЛЬНАЯ ПИЗДА ПО УМОЛЧАНИЮ». Глобально. На весь колхоз.
- Весринг видит две подходящие сущности, хватает ту, на которой висит
@Primary, и довольный такой идёт дальше. Делает вид, что другой вообще не существует. Просто и тупо.
@Qualifier — это когда ты, ебаный царь, в каждой конкретной точке говоришь: «Слушай сюда, блядь, мне в это поле воткни не первую попавшуюся пизду, а именно ту, которая называется, например, "смсШлюха"».
- Это точечный, императивный пиздец. Ты берёшь управление на себя и тыкаешь фреймворк мордой в нужный бин.
Пример, чтобы вообще всё стало ясно, как божий день:
// Две реализации одного интерфейса. Классика жанра.
@Component("смсРассылка") // Бин с именем "смсРассылка"
class SmsService implements NotificationService { /*...*/ }
@Component
@Primary // А ЭТО, БЛЯДЬ, ОФИЦИАЛЬНАЯ ДЕФОЛТНАЯ ПИЗДА!
class EmailService implements NotificationService { /*...*/ }
// Клиент, который всё это потребляет
@Component
public class MyClient {
// Сюда Весринг воткнёт EmailService. Почему? Потому что на нём @Primary!
// Он же дефолтный, его и суют везде, куда просят просто NotificationService.
@Autowired
private NotificationService сервисПоУмолчанию;
// А сюда, блядь, мы говорим чётко: "Да мне похуй на твой @Primary!
// Дай мне ту, что зовётся 'смсРассылка'!".
// И он, скрипя зубами, суёт SmsService.
@Autowired
@Qualifier("смсРассылка")
private NotificationService конкретныйСервис;
}
Ключевые отличия, если по-простому:
| Критерий | @Primary | @Qualifier |
|---|---|---|
| Что делает | Вешает на бин бирку «Бери меня, я главный!» | Ты в каждом месте орёшь: «Дай мне вот ЭТУ конкретную штуку!» |
| Где вешается | На саму реализацию, где @Component или @Bean |
Рядом с @Autowired, там, где ты эту хуйню используешь |
| Кто кого перебивает | Проигрывает, как лох. Если есть @Qualifier, про @Primary все забывают. |
Побеждает всегда. Царь и бог в точке инъекции. |
Практический совет, чтобы не выебать себе мозг:
Ставь @Primary на ту реализацию, которую ты используешь в 95% случаев — типа основной, дефолтной. А @Qualifier пускай будет у тебя как аварийный люк, когда в каком-то особом, ебучем месте тебе вдруг понадобилась другая реализация. Так и живём.