@Qualifier vs @Primary: Key Differences and Usage in Spring
@Primary marks a single bean as the default choice when multiple beans of the same type exist, while @Qualifier explicitly specifies which bean to inject by name. Use @Primary for a general default and @Qualifier for precise selection among multiple candidates.Quick Comparison
This table summarizes the main differences between @Qualifier and @Primary annotations in Spring.
| Aspect | @Primary | @Qualifier |
|---|---|---|
| Purpose | Marks a bean as the default when multiple beans exist | Specifies exactly which bean to inject by name |
| Number of Beans | Only one bean should be marked as primary per type | Can be used on multiple beans with different names |
| Usage Location | Placed on bean definition | Used on injection point or bean definition |
| Resolution | Spring injects primary bean automatically if no qualifier | Spring injects bean matching qualifier explicitly |
| Flexibility | Less flexible, one default per type | More flexible, can select any bean explicitly |
| Typical Use Case | Set a common default bean | Choose specific bean when multiple exist |
Key Differences
@Primary is used to mark one bean as the default choice when Spring finds multiple beans of the same type during dependency injection. If no other hints are given, Spring injects the @Primary bean automatically. This helps avoid ambiguity without specifying bean names everywhere.
On the other hand, @Qualifier is used to explicitly specify which bean to inject by its name or qualifier value. It can be placed on the injection point or on the bean definition itself. This is useful when you want to select a specific bean among many, overriding the default @Primary if present.
In summary, @Primary provides a default fallback bean, while @Qualifier gives precise control over which bean is injected. They can be used together: @Primary sets the default, and @Qualifier overrides it when needed.
Code Comparison
Example showing how @Primary works to select the default bean automatically.
import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; interface GreetingService { String greet(); } @Component @Primary class EnglishGreetingService implements GreetingService { public String greet() { return "Hello!"; } } @Component class SpanishGreetingService implements GreetingService { public String greet() { return "¡Hola!"; } } @Service class GreetingClient { private final GreetingService greetingService; @Autowired public GreetingClient(GreetingService greetingService) { this.greetingService = greetingService; } public String sayGreeting() { return greetingService.greet(); } } // When GreetingClient is used, EnglishGreetingService is injected by default because of @Primary.
@Qualifier Equivalent
Example showing how @Qualifier explicitly selects the bean to inject by name, overriding any @Primary.
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; interface GreetingService { String greet(); } @Component("englishService") class EnglishGreetingService implements GreetingService { public String greet() { return "Hello!"; } } @Component("spanishService") class SpanishGreetingService implements GreetingService { public String greet() { return "¡Hola!"; } } @Service class GreetingClient { private final GreetingService greetingService; @Autowired public GreetingClient(@Qualifier("spanishService") GreetingService greetingService) { this.greetingService = greetingService; } public String sayGreeting() { return greetingService.greet(); } } // GreetingClient injects SpanishGreetingService explicitly using @Qualifier("spanishService").
When to Use Which
Choose @Primary when you have one main bean implementation that should be the default for injection in most cases. It reduces the need to specify bean names everywhere and keeps code cleaner.
Choose @Qualifier when you need to inject a specific bean among multiple candidates, especially when the default @Primary bean is not suitable. It gives precise control and avoids ambiguity explicitly.
In practice, use @Primary to set a sensible default and @Qualifier to override that default in special cases.
Key Takeaways
@Primary sets a default bean for injection when multiple beans exist.@Qualifier explicitly selects which bean to inject by name or qualifier.@Primary for general default and @Qualifier for specific cases.@Primary provides fallback, @Qualifier overrides it.