What is the difference between @Primary and @Qualifier annotations?
In Spring Boot, both `@Primary` and `@Qualifier` annotations are used to resolve ambiguity when multiple beans of the same type are present in the application context and need to be injected into a dependency. However, they achieve this resolution through different mechanisms and have distinct use cases.
@Primary Annotation
The @Primary annotation is used to indicate that a particular bean should be given preference when multiple beans of the same type are available for autowiring. When Spring finds multiple beans of a specific type, and one of them is marked with @Primary, that bean will be chosen by default for injection, unless a more specific qualifier is provided. It acts as a default choice among multiple candidates.
Example of @Primary
@Component
public class EmailService implements MessageService {
@Override
public String sendMessage(String message) {
return "Email: " + message;
}
}
@Primary
@Component
public class SmsService implements MessageService {
@Override
public String sendMessage(String message) {
return "SMS: " + message;
}
}
// In a consuming class
@Service
public class NotificationService {
@Autowired
private MessageService messageService;
public String sendNotification(String message) {
return messageService.sendMessage(message);
}
// Here, SmsService will be injected by default because it's @Primary
}
@Qualifier Annotation
The @Qualifier annotation provides a way to explicitly specify which bean should be injected when multiple beans of the same type exist. It works in conjunction with @Autowired and allows you to narrow down the choice of bean by its name or a custom qualifier value. It offers fine-grained control over which specific bean is used for a particular dependency.
Example of @Qualifier
@Component("emailServiceImpl")
public class EmailService implements MessageService {
@Override
public String sendMessage(String message) {
return "Email: " + message;
}
}
@Component("smsServiceImpl")
public class SmsService implements MessageService {
@Override
public String sendMessage(String message) {
return "SMS: " + message;
}
}
// In a consuming class
@Service
public class NotificationService {
@Autowired
@Qualifier("emailServiceImpl")
private MessageService messageService;
public String sendNotification(String message) {
return messageService.sendMessage(message);
}
// Here, EmailService will be injected specifically because of @Qualifier
}
Key Differences
| Feature | @Primary | @Qualifier |
|---|---|---|
| Purpose | Designates a default bean among multiple candidates of the same type. | Explicitly specifies a particular bean by its name/qualifier value. |
| Specificity | Less specific; acts as a global default for a given type. | Highly specific; targets a single, named bean. |
| Usage | Applied at the bean definition level (on the class). | Applied at the injection point (on the field, constructor, or setter). |
| Default Behavior | Spring automatically injects the primary bean if no other specific instruction is given. | Requires explicit declaration at the injection point to select a specific bean. |
| Precedence | Lower precedence than `@Qualifier`. If both are present, `@Qualifier` takes precedence. | Higher precedence than `@Primary`. Always overrides `@Primary`. |
| Flexibility | Less flexible, as it sets a single default. | More flexible, allowing different beans of the same type to be injected into different locations. |
In summary, use @Primary when you have a general preference for one bean out of many identical types, serving as a fallback. Use @Qualifier when you need to precisely select a specific bean by its identifier at the injection point, offering more control and overriding @Primary if both are present. @Qualifier is generally preferred for explicit and clear dependency resolution.