Difference Between Spring @Qualifier and @Primary Annotations

In Spring Framework, dependency injection plays a vital role in managing the application's components. However, in situations where multiple beans of the same type exist, it can create ambiguity during autowiring. Spring provides two annotations, @Qualifier and @Primary, to tackle such scenarios and ensure precise bean injection.
 
In this blog post, we will explore the differences between these annotations and demonstrate their use with practical examples.

@Qualifier Annotation

The @Qualifier annotation is used to resolve ambiguity when multiple beans of the same type are present in a Spring application context. It allows you to specify a specific bean to be injected by using a qualifier value.

The @Qualifier annotation is used in conjunction with @Autowired to avoid confusion when we have two or more beans configured for the same type. If there are multiple implementations for a single interface then we can use @Qualifier to choose the required implementation at runtime.

For example, consider we have a MessageService interface with multiple implementations - EmailServiceSMSService, and TwitterService classes.

MessageService interface

public interface MessageService {
    public void sendMsg(String message);
}
Next, let's create implementations - EmailServiceSMSService, and TwitterService classes.

EmailService Class

public class EmailService implements MessageService{

    public void sendMsg(String message) {
         System.out.println(message);
    }
}

SMSService Class

public class TwitterService implements MessageService{

    public void sendMsg(String message) {
        System.out.println(message);
    }
}

TwitterService Class

public class SMSService implements MessageService{

    public void sendMsg(String message) {
         System.out.println(message);
    }
}

MessageProcessor Interface and MessageProcessorImpl Class

It's time to see the usage of @Qualifier annotation.
public interface MessageProcessor {
    public void processMsg(String message);
}

public class MessageProcessorImpl implements MessageProcessor {

    private MessageService messageService;

    // setter based DI
    @Autowired
    @Qualifier("twitterService")
    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
 
    // constructor based DI
    @Autowired
    public MessageProcessorImpl(@Qualifier("twitterService") MessageService messageService) {
        this.messageService = messageService;
    }
 
    public void processMsg(String message) {
        messageService.sendMsg(message);
    }
}
In the above example, Dependency is injected by both setter and constructor so you can use either one of them.
We have used @Qualifier to inject TwitterService bean using constructor injection:
    // setter based DI
    @Autowired
    @Qualifier("twitterService")
    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
We have used @Qualifier to inject the TwitterService bean using setter injection:
    // constructor based DI
    @Autowired
    public MessageProcessorImpl(@Qualifier("twitterService") MessageService messageService) {
        this.messageService = messageService;
    }
If you want to inject EmailService bean instead of TwitterService bean then you can simply pass bean EmailService bean name. 
For example:
    // constructor based DI
    @Autowired
    public MessageProcessorImpl(@Qualifier("emailService") MessageService messageService) {
        this.messageService = messageService;
    }
Check out complete code example: Spring @Qualifier Annotation Example

@Primary Annotation

The @Primary annotation is used to indicate a default bean when multiple beans of the same type are present. If multiple beans are eligible for autowiring and none of them are explicitly specified using @Qualifier, the bean marked with @Primary will be selected by default.

Suppose we have two beans implementing the MailSender interface - EmailSender and SmsSender. To set EmailSender as the default bean for autowiring, we can use the @Primary annotation.
@Component
@Primary
public class EmailSender implements MailSender {
    // ...
}

@Component
public class SmsSender implements MailSender {
    // ...
}

@Service
public class NotificationService {
    @Autowired
    private MailSender mailSender;
    // ...
}
Complete code example: Spring @Primary Annotation Example

Conclusion

To summarize, the @Qualifier annotation is used to resolve ambiguity when multiple beans of the same type exist, whereas the @Primary annotation designates a default bean to be injected when no qualifier is specified. They serve different purposes and can be used together or individually, depending on the desired behavior of bean injection.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare