Open In App

Spring @Qualifier Annotation with Example

Improve
Improve
Like Article
Like
Save
Share
Report

Spring is one of the most popular Java EE frameworks. It is an open-source lightweight framework that allows Java EE 7 developers to build simple, reliable, and scalable enterprise applications. This framework mainly focuses on providing various ways to help you manage your business objects. It made the development of Web applications much easier than compared to classic Java frameworks and application programming interfaces (APIs), such as Java database connectivity (JDBC), JavaServer Pages(JSP), and Java Servlet. This framework uses various new techniques such as Aspect-Oriented Programming (AOP), Plain Old Java Object (POJO), and dependency injection (DI), to develop enterprise applications. Now talking about Spring Annotation

Spring Annotations are a form of metadata that provides data about a program. Annotations are used to provide supplemental information about a program. It does not have a direct effect on the operation of the code they annotate. It does not change the action of the compiled program. 

One of the most important annotations in spring is @Qualifier annotation which is used to eliminate the issue of which bean needs to be injected. Let’s understand this line by an example. 

Note: It is highly recommended that you need first understand the Spring @Autowired Annotation before jumping into @Qualifier Annotation.

Implementation: 

Let’s first understand the problem with the @Autowired Annotation then we will understand why @Qualifier Annotation has been introduced. So first let’s create a class named Human and Human class does has a dependency on another class named Heart

A File: Human.java

Java




public class Human {
    private Heart heart;
}


B File: Heart.java

This class has only one simple method named pump().

Java




public class Heart {
    public void pump() {
        System.out.println("Heart is Pumping");
    }
}


Now we want to inject the object of the Heart class inside the Human class by using the @Autowired annotation. So for this thing, we can write the code something like this

Example 

Java




// Java Program to Illustrate Injection of object of the
// Heart class inside the Human class using the @Autowired
// annotation
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
// Class
public class Human {
 
    private Heart heart;
 
    // Annotation
    @Autowired public void setHeart(Heart heart)
    {
        this.heart = heart;
    }
 
    // Method
    // Calling method of Heart class
    public void startPumping() { heart.pump(); }
}


C File: beans.xml
 So in the beans.xml file, we can write the code something like this

XML




<?xml version="1.0" encoding="UTF-8"?>
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 
    <context:annotation-config/>
 
    <bean id="heartObjValue" class="Heart"></bean>
    <bean id="humanObject" class="Human"></bean>
  
</beans>


D Application class 

And in the main class, we can write the code something like this

Java




// Java Program to Illustrate Application Class
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
// Application class
// Main class
public class Main {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating an new class path
        ApplicationContext context
            = new ClassPathXmlApplicationContext(
                "beans.xml");
        Human human
            = context.getBean("humanObject", Human.class);
        human.startPumping();
    }
}


Output: 

Heart is Pumping

Output explanation

So the above code executes fine. Now let’s have a brief explanation of what happens in the above code. So whenever you put a @Autowired annotation before the setter method in Human class this is going to autowire the object of the Heart class into Human class by using the mechanism of Spring Autowiring ‘byType’

Note: How @Autowired Work?

  1. First, it tries to resolves with “byType”.
  2. If “byType” fails then it goes with “byName”.

 

So in our above example, the “byType” Spring Autowiring mechanism happens and the heart object is injected into the Human class. But where is the problem lie? Now inside the beans.xml file let’s create another bean of the Heart class. We can write the code something like this. Now our modified beans.xml file is 

XML




<?xml version="1.0" encoding="UTF-8"?>
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
 
    <context:annotation-config/>
 
    <bean id="humanHeart" class="Heart"></bean>
    <bean id="octpusHeart" class="Heart"></bean>
 
    <bean id="humanObject" class="Human"></bean>
 
</beans>


Here we have two beans of the same class one is “humanHeart” and another one is “octpusHeart”. So in that scenario, both “byType” and “byName” Spring Autowiring are going to be failed. Because there are two beans for the same class Heart and the id is not matching with the object “heart”. So whenever you are going to run your application so you are going to get the following exceptions.

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'humanObject': Unsatisfied dependency expressed through method 'setHeart' parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'Heart' available: expected single matching bean but found 2: humanHeart,octpusHeart
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.resolveMethodArguments(AutowiredAnnotationBeanPostProcessor.java:768)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:720)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1413)

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'Heart' available: expected single matching bean but found 2: humanHeart,octpusHeart
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1358)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300)

And this is where @Qualifier Annotation comes into the picture. So whenever both “byType” and “byName” Spring Autowiring is going to be failed we can use the @Qualifier Annotation before the setter method and we can mention the bean id inside that. For example, in the case of the Human class, we need the “humanHeart” bean, so we can mention that bean inside the @Qualifier Annotation. So we can write something like this to resolve this error.

Example: Modified Human.class File 

Java




// Java Program to Illustrate Modified Human Class
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
// Class
public class Human {
 
    private Heart heart;
 
    // Annotation
    @Autowired
    @Qualifier("humanHeart")
 
    // Setter
    public void setHeart(Heart heart)
    {
        this.heart = heart;
    }
 
    // Method
    public void startPumping() { heart.pump(); }
}


Output:

Heart is Pumping

One more interesting thing is we can also use these annotations before the dependency. There is no need for any setter method. So we can write something like this also. 

Java




// Java Program to Illustrate Modified Human Class
// Where we used these annotations before the dependency
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
// Class
public class Human {
 
    @Autowired @Qualifier("humanHeart") private Heart heart;
 
    // Method
    public void startPumping() { heart.pump(); }
}


 
 

Conclusion: Spring @Autowired Annotation first looks for “byType” if there is any conflict then it is going to look for “byName”. And if any conflict with “byName”, resolve that with @Qualifier Annotation.



Last Updated : 22 Feb, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads