🌱 Spring Boot Q46 / 56

What is the difference between @Primary and @Qualifier annotations?

AI-Powered Answer ✓ Answered

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

java
@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

java
@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
PurposeDesignates a default bean among multiple candidates of the same type.Explicitly specifies a particular bean by its name/qualifier value.
SpecificityLess specific; acts as a global default for a given type.Highly specific; targets a single, named bean.
UsageApplied at the bean definition level (on the class).Applied at the injection point (on the field, constructor, or setter).
Default BehaviorSpring automatically injects the primary bean if no other specific instruction is given.Requires explicit declaration at the injection point to select a specific bean.
PrecedenceLower precedence than `@Qualifier`. If both are present, `@Qualifier` takes precedence.Higher precedence than `@Primary`. Always overrides `@Primary`.
FlexibilityLess 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.