Spring @Qualifier Annotation Example

In this tutorial, we will see how to use Spring or Spring Boot @Qualifier annotation to resolve ambiguous dependencies.

Spring @Qualifier Annotation Overview

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.

YouTube Video - @Qualifier Annotation

Spring @Qualifier Annotation Example

Let's take a Message Processing Example - a message can be sent in many ways like Email, SMS, Twitter, etc.
 
Let's create a MessageService interface for multiple message service implementations - EmailService, SMSService, and TwitterService classes.

MessageService interface

public interface MessageService {
    public void sendMsg(String message);
}
Next, let's create implementations - EmailService, SMSService, 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;
    }

AppConfiguration

Let's write the java based configuration.
@Configuration
@ComponentScan("com.javadevsguide.springframework.di")
public class AppConfiguration {

    @Bean(name="emailService")
    public MessageService emailService(){
         return new EmailService();
    }
 
    @Bean(name="twitterService")
    public MessageService twitterService(){
        return new TwitterService();
    }
 
    @Bean(name="smsService")
    public MessageService smsService(){
        return new SMSService();
    }
 
    @Bean
    public MessageProcessor messageProcessor(){
        return new MessageProcessorImpl(twitterService());
    }
}

Testing

Let's test the example using the Spring IOC container which is an ApplicationContext object.
public class TestApplication {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfiguration.class);
        MessageProcessor processor = applicationContext.getBean(MessageProcessor.class);
        processor.processMsg("twitter message sending ");
    }
}
Output:
twitter message sending 

Conclusion

In this example, we have seen how to use @Qualifier annotation in conjunction with @Autowired to avoid confusion when we have two or more beans configured for the same type.

The source code of this tutorial is available on my GitHub Repository: Spring @Qualifier Annotation Example

Spring Framework Related Posts

Comments