@Qualifier and @Primary — Resolving Ambiguous Injection
Fast recall
Quick revision
Core answer
NoUniqueBeanDefinitionException unless you resolve the ambiguity. `@Primary` marks a default candidate for type-only matches. `@Qualifier("name")` specifies an explicit bean name at the injection point and overrides `@Primary`. The resolution order: `@Qualifier` > `@Primary` > field name. The qualifier value must match the bean name exactly with a lowercase first letter (@Qualifier("smsNotifier") not "SmsNotifier"). For type-safety in large codebases, build custom qualifier annotations (@Stripe PaymentGateway gateway) that fail at compile time on typos, instead of fragile string-based qualifiers.Understanding of Spring's bean resolution algorithm and when each annotation is the right tool.
Thinking @Primary and @Qualifier do the same thing; not knowing that @Qualifier takes precedence over @Primary, or that you can create custom qualifier annotations.
Explain how to create a custom qualifier annotation to group beans semantically rather than by name, which is more refactoring-safe than string-based qualifiers.
Interview-ready guide
Interview answer
When Spring finds multiple beans of the same type, it refuses to guess which one to inject — NoUniqueBeanDefinitionException at startup. @Primary and @Qualifier are the two tools that break the tie, and they follow a clear precedence order.
`@Primary`
- Marks the default candidate — any injection point that asks for
Notifierby type getsEmailNotifierwithout needing a qualifier - When
@Qualifieris also present at the injection point,@Qualifierwins — it is more specific and completely overrides@Primary - Putting
@Primaryon two beans of the same type does not resolve the ambiguity — Spring throwsNoUniqueBeanDefinitionExceptionagain
`@Qualifier`
- Provides explicit selection at the injection point — names exactly which bean is wanted
- The value must match the bean name exactly, lowercase first letter —
@Qualifier("SmsNotifier")produces aNoSuchBeanDefinitionException, not a type-match failure - Custom qualifier annotations are type-safe:
@Stripe PaymentGateway gateway— typos fail at compile time, not at deployment
The field name fallback
- Spring's last-resort fallback — declare
private Notifier smsNotifierand Spring matches a bean namedsmsNotifierwithout any annotation - Works, but rename the field and injection silently breaks
- Custom qualifier annotations are the production-ready approach
Collection and generic injection
Listinjects all implementations;Mapkeys by bean name — ideal for strategy-pattern dispatch- Generics work as implicit qualifiers since Spring 4.0 —
RepositoryandRepositoryresolve correctly without annotations
@Qualifier and @Primary — Resolving Ambiguous Injection
Direct Answer
When multiple beans of the same type exist, Spring throws NoUniqueBeanDefinitionException unless you resolve the ambiguity. @Primary marks a default candidate for type-only matches. @Qualifier("name") specifies an explicit bean name at the injection point and overrides @Primary. The resolution order: @Qualifier > @Primary > field name. The qualifier value must match the bean name exactly with a lowercase first letter (@Qualifier("smsNotifier") not "SmsNotifier"). For type-safety in large codebases, build custom qualifier annotations (@Stripe PaymentGateway gateway) that fail at compile time on typos, instead of fragile string-based qualifiers.
Common Mistakes & Pitfalls
Thinking @Primary and @Qualifier do the same thing; not knowing that @Qualifier takes precedence over @Primary, or that you can create custom qualifier annotations.
Check your understanding
Answer these without looking back at the article.
- What happens if you put @Primary on two beans of the same type?
- How does Spring resolve ambiguity when no @Primary or @Qualifier is present — does it always throw?
- Can you use @Qualifier with constructor injection and @Bean factory methods?
- How would you build a custom @Qualifier annotation for type-safe selection?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.