@Qualifier annotation in Spring

In this article, we will learn what is @Qualifier annotation in spring with the help of examples.

Definition

Qualifier the term means the one WHO QUALIFIES. Qualifier annotation is used to know which java bean is qualified to be used in a program. If the beans are of different types then it is not an issue, the issue arises when the beans are of the same type.

Beans of different types

package com.getinputs.qualifier;
import org.springframework.stereotype.Component;

@Component
public class Manager {
  public void getResponsibility() {
    System.out.println("Manages and coordinate with employees");
  }
}
package com.getinputs.qualifier;
import org.springframework.stereotype.Component;

@Component
public class SEDeveloper {
  public void getResponsibility() {
    System.out.println("Developing and testing the codebase");
  }
}
package com.getinputs.qualifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BusinessClient {

  @Autowired
  Manager manager;

  public void getResponsibility() {
    manager.getResponsibility();
  }
}

Note : "BusinessClient" knows it needs the "Manager" bean
package com.getinputs.qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class QualifierDemo {
  public static void main(String[] args) {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

    context.scan("com.getinputs.qualifier");
    context.refresh();

    BusinessClient businessClient = context.getBean(BusinessClient.class);
    businessClient.getResponsibility();
  }
}

O/P : Manages and coordinate with employees

In the above example Manager and SEDeveloper beans are of 2 different types. The BusinessClient class asks for Manager bean hence the spring container provides Manager bean. Now consider a case where there is a relationship between the Manager and SEDeveloper beans, we will try to understand it better below.

Beans of the same type

package com.getinputs.qualifier;

public interface Employee {
  public void getResponsibility();
}
package com.getinputs.qualifier;
import org.springframework.stereotype.Component;

@Component
public class Manager implements Employee {
  public void getResponsibility() {
    System.out.println("Manages and coordinate with employees");
  }
}
package com.getinputs.qualifier;
import org.springframework.stereotype.Component;

@Component
public class SEDeveloper implements Employee {
  public void getResponsibility() {
    System.out.println("Developing and testing the codebase");
  }
}

Manager and SEDeveloper implements the same Employee interface, now in BusinessClient we will Autowire the Employee interface and check the behavior.

package com.getinputs.qualifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BusinessClient {
  @Autowired
  Employee employee;

  public void getResponsibility() {
    employee.getResponsibility();
  }
}
package com.getinputs.qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class QualifierDemo {
  public static void main(String[] args) {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

    context.scan("com.getinputs.qualifier");
    context.refresh();

    BusinessClient businessClient = context.getBean(BusinessClient.class);
    businessClient.getResponsibility();
  }
}

Output : Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.getinputs.qualifier.Employee’ available: expected single matching bean but found 2: manager,SEDeveloper

The Spring container gets confused because there are 2 beans that are of the same Employee type and it’s an ambiguity issue. So to remove such kind of ambiguity issue we have to use Qualifier annotation.

Using @Qualifier annotation without alias name

package com.getinputs.qualifier;
public interface Employee {
  public void getResponsibility();
}
package com.getinputs.qualifier;
import org.springframework.stereotype.Component;

@Component("manager")
public class Manager implements Employee {
  public void getResponsibility() {
    System.out.println("Manages and coordinate with employees");
  }
}

Note : Given a alias as "manager"
package com.getinputs.qualifier;
import org.springframework.stereotype.Component;

@Component("seDeveloper")
public class SEDeveloper implements Employee {
  public void getResponsibility() {
    System.out.println("Developing and testing the codebase");
  }
}

Note : Given a alias as "seDeveloper"
package com.getinputs.qualifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class BusinessClient {
  @Autowired
  @Qualifier("manager")
  Employee employee;

  public void getResponsibility() {
    employee.getResponsibility();
  }
}

Note : Using the Qualifier annotation we are giving a instruction to Container to use the "Manager" bean.
package com.getinputs.qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class QualifierDemo {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.scan("com.getinputs.qualifier");
    context.refresh();

    BusinessClient businessClient = context.getBean(BusinessClient.class);
    businessClient.getResponsibility();
  }
}

O/P : Manages and coordinate with employees

Important Note: Instead of using the name from the Component annotation we can make use of the Qualifier annotation in the Bean classes.

Using @Qualifier annotation with alias name

package com.getinputs.qualifier;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("manager")
@Qualifier("alias-manager")
public class Manager implements Employee {
  public void getResponsibility() {
    System.out.println("Manages and coordinate with employees");
  }
}
package com.getinputs.qualifier;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class BusinessClient {
  @Autowired
  @Qualifier("alias-manager")
  Employee employee;

  public void getResponsibility() {
    employee.getResponsibility();
  }
}

Note : In BusinessClient class we can make use of "manager" alias or "alias-manager" alias . Both will work as expected .
package com.getinputs.qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class QualifierDemo {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.scan("com.getinputs.qualifier");
    context.refresh();

    BusinessClient businessClient = context.getBean(BusinessClient.class);
    businessClient.getResponsibility();
  }
}

O/P : Manages and coordinate with employees

I hope you found this article interesting and valuable. If you are having any concerns or questions about this article please comment below.

Leave a Comment