Strategy Pattern with Spring @Qualifier
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
When you use Strategy in Spring, you end up with several beans of the same type — say three classes implementing ShippingStrategy, all annotated at Component.
If a service just autowires ShippingStrategy, Spring doesn't know which one to give it and throws a NoUniqueBeanDefinitionException. There are two clean fixes. The first is at Qualifier, for a fixed choice.
You give each bean a name, then on the injection point — the constructor parameter — you add at Qualifier with the name you want, like express. Spring finds that exact bean and wires it once at startup. The second, and more powerful, approach is map injection for runtime selection.
You declare a constructor parameter of type Map of String to ShippingStrategy. Spring automatically fills that map with every ShippingStrategy bean, using the bean name as the key. Now at runtime you do a map lookup with a string — like the shipping type the user chose — and call the strategy you get back.
The key thing to know is that the map keys are bean names. If you write at Component with an explicit name like express, the key is express. If you just write at Component with no name, the key defaults to the class name with the first letter lowercased.
A null lookup almost always means the key doesn't match the actual bean name. The big mistake is calling new ExpressShipping inside the service. That throws away everything the container gives you — you can't mock it in tests, you lose lifecycle management, and you can't swap implementations without editing code.
Always inject. And if one implementation should be the default, mark it at Primary instead of qualifying every single injection point.
Strategy Pattern with Spring @Qualifier
Direct Answer
When several beans implement one strategy interface, Spring can't autowire it alone — it throws NoUniqueBeanDefinitionException. Give each implementation a name and select it with @Qualifier for a fixed choice, or inject a Map<String, Strategy> that Spring auto-fills with every bean (keyed by bean name) for runtime selection.
Common Mistakes & Pitfalls
new StrategyImpl()in the context. Bypasses Spring entirely — no mocking, no lifecycle, no swapping. Always inject.- Qualifier on the class but not the injection point. You must add
@Qualifierwhere the bean is consumed, not only where it's defined, or Spring still can't disambiguate. - Assuming map keys. The key is the bean name. With bare
@Componentit's the class name with the first letter lowercased (expressShipping), not"express". A null lookup usually means a wrong key. - Forgetting
@Primaryexists. When one implementation should be the default, mark it@Primaryinstead of qualifying every injection point.
Check your understanding
Answer these without looking back at the article.
- How do you handle an unknown key in the Map lookup?
- What is @Primary in Spring and when would you use it alongside @Qualifier?
- How does @Profile help select strategies per environment?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.