Question 28 · Section 5

What is @Qualifier?

4. Map -> alternative for dynamic selection 5. Avoid strings -> typos 6. In Spring Boot 3+ (Jakarta EE) annotation moved from javax.inject to jakarta.inject. Functionality is th...

Language versions: English Russian Ukrainian

Junior Level

@Qualifier specifies which exact bean to inject.

// Two beans of PaymentService type
@Bean public PaymentService stripe() { ... }
@Bean public PaymentService paypal() { ... }

// Selection via @Qualifier:
@Autowired
@Qualifier("stripe")
private PaymentService payment;

Why:

  • When there are multiple beans of the same type
  • To specify the exact one needed

Middle Level

How It Works

1. Spring finds all beans of the type
2. If @Qualifier exists -> filters by name/annotation
3. @Qualifier > @Primary in priority. @Qualifier is an explicit specification of a particular bean,
Spring considers it more precise. @Primary is a global "default" marker.
Explicit choice always takes priority.

On @Bean Methods

@Configuration
public class Config {

    @Bean
    @Qualifier("fast")
    public RestTemplate fastRestTemplate() { ... }

    @Bean
    @Qualifier("slow")
    public RestTemplate slowRestTemplate() { ... }
}

Custom Qualifiers

@Qualifier  // Meta-annotation!
@Retention(RUNTIME)
public @interface FastService { }

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

@Autowired
@FastService
private Service service;

// -> Type-safe, no strings!

Senior Level

Priority

@Qualifier > @Primary > byName > @Priority

-> If @Qualifier exists -> @Primary is ignored!

With Attributes

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

// Spring matches ALL attributes!
@Database(value = "postgres", readOnly = true)
@Bean
public DataSource readOnlyDb() { ... }

ObjectProvider Limitation

// Programmatic qualifier selection is difficult
// Solution: Map<String, T>
@Autowired
Map<String, Service> services;

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

Production Experience

Real scenario: typo in string

@Qualifier("fastService")  // Forgot "s"
-> NoSuchBeanDefinitionException

Solution: custom annotations
-> Compiler catches errors

Best Practices

  1. Custom annotations -> type-safe
  2. @Qualifier > @Primary -> priority
  3. On @Bean methods -> for multiple beans
  4. Map -> alternative for dynamic selection
  5. Avoid strings -> typos
  6. In Spring Boot 3+ (Jakarta EE) annotation moved from javax.inject to jakarta.inject. Functionality is the same.

Summary for Senior

  • @Qualifier -> choice clarification
  • @Qualifier > @Primary -> priority
  • Custom annotations -> type-safe
  • Attributes -> fine-tuning
  • Map -> dynamic selection
  • Avoid strings -> typos

Interview Cheat Sheet

Must know:

  • @Qualifier specifies which exact bean to inject when there are multiple of the same type
  • Priority: @Qualifier > @Primary > byName > @Priority
  • @Qualifier goes on @Bean methods and injection points (@Autowired, constructor)
  • Custom qualifiers: @Qualifier as meta-annotation -> type-safety, no typo strings
  • Custom qualifiers with attributes: Spring matches ALL attributes of the qualifier annotation
  • In Spring Boot 3+ (Jakarta EE) @Qualifier moved from javax.inject to jakarta.inject
  • Map<String, T> - alternative for dynamic selection without @Qualifier

Common follow-up questions:

  • What is more important: @Qualifier or @Primary? - @Qualifier always takes priority; when @Qualifier is present, @Primary is ignored.
  • Why are custom qualifiers better than strings? - Compiler checks types; typos in strings are caught only at runtime.
  • Can @Qualifier be used with attributes? - Yes, Spring matches all attributes of a custom qualifier annotation.
  • What happens on a typo in @Qualifier string? - NoSuchBeanDefinitionException - bean with that name not found.

Red flags (DO NOT say):

  • “@Primary overrides @Qualifier” - no, @Qualifier always takes priority.
  • “@Qualifier searches bean by type” - no, @Qualifier filters by name/annotation among beans of the same type.
  • “Strings in @Qualifier are best practice” - no, custom annotations are type-safe.
  • “@Qualifier works only with @Autowired” - no, also on @Inject, @Bean, constructor parameters.

Related topics:

  • [[27. What to do if there are multiple beans of the same type]]
  • [[26. What does the Autowired annotation do]]
  • [[24. What is a Configuration class]]
  • [[25. Difference between Component Service Repository Controller]]