Вопрос 28 · Раздел 5

Что такое @Qualifier?

4. Map → альтернатива для динамического выбора 5. Избегайте строк → опечатки 6. В Spring Boot 3+ (Jakarta EE) аннотация переехала из javax.inject в jakarta.inject. Функционально...

Версии по языкам: English Russian Ukrainian

🟢 Junior Level

@Qualifier — уточняет, какой именно бин нужно внедрить.

// Два бина типа PaymentService
@Bean public PaymentService stripe() { ... }
@Bean public PaymentService paypal() { ... }

// Выбор через @Qualifier:
@Autowired
@Qualifier("stripe")
private PaymentService payment;

Зачем:

  • Когда несколько бинов одного типа
  • Чтобы точно указать нужный

🟡 Middle Level

Как работает

1. Spring находит все бины типа
2. Если есть @Qualifier → фильтрует по имени/аннотации
3. @Qualifier > @Primary по приоритету. @Qualifier — явное указание конкретного бина,
Spring рассматривает его как более точное. @Primary — глобальная метка «по умолчанию».
Явный выбор всегда приоритнее.

На @Bean методах

@Configuration
public class Config {
    
    @Bean
    @Qualifier("fast")
    public RestTemplate fastRestTemplate() { ... }
    
    @Bean
    @Qualifier("slow")
    public RestTemplate slowRestTemplate() { ... }
}

Кастомные квалификаторы

@Qualifier  // ← Мета-аннотация!
@Retention(RUNTIME)
public @interface FastService { }

@FastService
@Bean
public Service fastService() { ... }

@Autowired
@FastService
private Service service;

// → Типобезопасно, нет строк!

🔴 Senior Level

Приоритет

@Qualifier > @Primary > byName > @Priority

→ Если есть @Qualifier → @Primary игнорируется!

С параметрами

@Qualifier
@Retention(RUNTIME)
public @interface Database {
    String value() default "postgres";
    boolean readOnly() default false;
}

// Spring сопоставляет ВСЕ атрибуты!
@Database(value = "postgres", readOnly = true)
@Bean
public DataSource readOnlyDb() { ... }

ObjectProvider ограничение

// Программный выбор квалификатора затруднён
// Решение: Map<String, T>
@Autowired
Map<String, Service> services;

Service service = services.get("fast");

Production Experience

Реальный сценарий: опечатка в строке

@Qualifier("fastService")  // Забыли "s"
→ NoSuchBeanDefinitionException

Решение: кастомные аннотации
→ Компилятор ловит ошибки

Best Practices

  1. Кастомные аннотации → типобезопасно
  2. @Qualifier > @Primary → приоритет
  3. На @Bean методах → для нескольких бинов
  4. Map → альтернатива для динамического выбора
  5. Избегайте строк → опечатки
  6. В Spring Boot 3+ (Jakarta EE) аннотация переехала из javax.inject в jakarta.inject. Функциональность та же.

Резюме для Senior

  • @Qualifier → уточнение выбора
  • @Qualifier > @Primary → приоритет
  • Кастомные аннотации → типобезопасно
  • Атрибуты → тонкая настройка
  • Map → динамический выбор
  • Избегайте строк → опечатки

🎯 Шпаргалка для интервью

Обязательно знать:

  • @Qualifier уточняет, какой именно бин внедрить, когда их несколько одного типа
  • Приоритет: @Qualifier > @Primary > byName > @Priority
  • @Qualifier ставится на @Bean методы и на точки инъекции (@Autowired, конструктор)
  • Кастомные квалификаторы: @Qualifier как мета-аннотация → типобезопасность, нет строк-опечаток
  • Кастомные квалификаторы с атрибутами: Spring сопоставляет ВСЕ атрибуты аннотации
  • В Spring Boot 3+ (Jakarta EE) @Qualifier переехал из javax.inject в jakarta.inject
  • Map<String, T> — альтернатива для динамического выбора без @Qualifier

Частые уточняющие вопросы:

  • Что важнее: @Qualifier или @Primary? — @Qualifier всегда приоритетнее; при наличии @Qualifier @Primary игнорируется.
  • Почему кастомные квалификаторы лучше строк? — Компилятор проверяет типы; опечатки в строках ловятся только в рантайме.
  • Можно ли использовать @Qualifier с атрибутами? — Да, Spring сопоставляет все атрибуты кастомной аннотации-квалификатора.
  • Что будет при опечатке в строке @Qualifier? — NoSuchBeanDefinitionException — бин с таким именем не найден.

Красные флаги (НЕ говорить):

  • «@Primary переопределяет @Qualifier» — нет, @Qualifier всегда приоритетнее.
  • «@Qualifier ищет бин по типу» — нет, @Qualifier фильтрует по имени/аннотации среди бинов одного типа.
  • «Строки в @Qualifier — лучшая практика» — нет, кастомные аннотации типобезопаснее.
  • «@Qualifier работает только с @Autowired» — нет, также на @Inject, @Bean, параметрах конструктора.

Связанные темы:

  • [[27. Что делать, если есть несколько бинов одного типа]]
  • [[26. Что делает аннотация @Autowired]]
  • [[24. Что такое @Configuration класс]]
  • [[25. В чём разница между @Component, @Service, @Repository, @Controller]]