Питання 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]]