Spring Custom Qualifier Annotation

By Arvind Rai, March 28, 2022
This page will walk through Spring custom qualifier annotation example.
1. A custom qualifier annotation is created using @Qualifier annotation.
2. The custom qualifier annotations are created with value() method or without any method.
3. We can also use one or more than one custom methods to create custom qualifiers.
4. Custom qualifiers are useful to fix dependency injection in custom way when more than one beans are eligible for autowiring.
5. Our component can be marked with custom qualifier at class level that will take part in selection of bean for dependency injection.
6. In XML, <qualifier> element is used to let custom qualifier decide to select bean for autowiring using XML.

Custom Qualifier with Bean Meta Tag and Qualifier Attribute Tag in XML

To create a custom qualifier, we need to create an annotation which will be annotated with @Qualifier. Here we will define our custom methods on the basis of which we will select bean for autowiring. Find the custom qualifier.
PersonQualifier.java
package com.concretepage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Qualifier;
@Target({ElementType.FIELD, ElementType.METHOD,
        ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface PersonQualifier {
	String status();
	String quality();
} 
In XML file, we use <meta> tag or qualifier <attribute> tag to define criteria to qualify for bean dependency injection. First we will provide example with <meta> tag.
app-conf-1.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

		<context:annotation-config/>
		<bean class="com.concretepage.bean.PersonService"/>
		<bean class="com.concretepage.bean.Student">
			<meta key="status" value="Rich"/>
			<meta key="quality" value="Bad"/>
			<property name="personName" value="Student Kansh"/>
		</bean>		
		<bean class="com.concretepage.bean.Teacher">
		        <meta key="status" value="Poor"/>
			<meta key="quality" value="Good"/>
			<property name="personName" value="Teacher Sudama"/>
		</bean>		
</beans> 
Now if we want to use <attribute> tag of <qualifier> tag, we do as follows.
app-conf-2.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

		<context:annotation-config/>
		<bean class="com.concretepage.bean.PersonService"/>
		<bean class="com.concretepage.bean.Student">
		    <qualifier type="PersonQualifier">
			     <attribute key="status" value="Rich"/>
			     <attribute key="quality" value="Bad"/>
		    </qualifier>
		    <property name="personName" value="Student Kansh"/>
		</bean>		
		<bean class="com.concretepage.bean.Teacher">
		    <qualifier type="PersonQualifier">
			    <attribute key="status" value="Poor"/>
			    <attribute key="quality" value="Good"/>
		    </qualifier>
		    <property name="personName" value="Teacher Sudama"/>
		</bean>		
</beans> 
Now find the service class which will use our custom qualifier.
PersonService.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import com.concretepage.PersonQualifier;
public class PersonService {
	@Autowired
	@PersonQualifier(status="Poor", quality="Good")
	private Person person;
	public Person getPerson() {
		return person;
	}
	public void setPerson(Person person) {
		this.person = person;
	}
} 
The field person will be autowired using the bean which follow the criteria defined by @PersonQualifier and this will be Teacher class in our case.

Find other classes used in our example.
Person.java
package com.concretepage.bean;
public class Person {
	private String personName;
	public String getPersonName() {
		return personName;
	}
	public void setPersonName(String personName) {
		this.personName = personName;
	}
} 
Student.java
package com.concretepage.bean;
public class Student extends Person {
	private String stdLocation;
	public String getStdLocation() {
		return stdLocation;
	}
	public void setStdLocation(String stdLocation) {
		this.stdLocation = stdLocation;
	}
} 
Teacher.java
package com.concretepage.bean;
public class Teacher extends Person{
	private String subject;
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
} 
SpringDemo.java
package com.concretepage;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.concretepage.bean.PersonService;
public class SpringDemo {
	public static void main(String[] args) {
		AbstractApplicationContext  context = new ClassPathXmlApplicationContext("app-conf-1.xml");
		PersonService service = context.getBean(PersonService.class);
		System.out.println(service.getPerson().getPersonName());
		context.close();
	}
} 
Find the output.
Teacher Sudama 
Test the application using file app-conf-2.xml, we will get the same result.

Custom Qualifier with value() Method using Java Configuration

Here we will create a custom qualifier with value() method. For the example we are creating an enum for some constant value. We will also create two components that will be annotated by custom qualifier at class level. Find the example using Java configuration
AnimalQualifier.java
package com.concretepage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Qualifier;
@Target({ElementType.FIELD, ElementType.METHOD,
        ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AnimalQualifier {
	AnimalType value();
} 
AnimalType.java
package com.concretepage;
public enum AnimalType {
  DEER, FOX	
} 
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages="com.concretepage.bean")
public class AppConfig {
} 
Animal.java
package com.concretepage.bean;
public interface Animal {
	void printName();
} 
Deer.java
package com.concretepage.bean;
import org.springframework.stereotype.Component;
import com.concretepage.AnimalQualifier;
import com.concretepage.AnimalType;
@Component
@AnimalQualifier(AnimalType.DEER)
public class Deer implements Animal {
	@Override
	public void printName() {
		System.out.println("---  Deer  ---");
	}
} 
Fox.java
package com.concretepage.bean;
import org.springframework.stereotype.Component;
import com.concretepage.AnimalQualifier;
import com.concretepage.AnimalType;
@Component
@AnimalQualifier(AnimalType.FOX)
public class Fox implements Animal {
	@Override
	public void printName() {
		System.out.println("---  Fox  ---");
	}
} 
AnimalService.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.concretepage.AnimalQualifier;
import com.concretepage.AnimalType;
@Service
public class AnimalService {
	@Autowired
	@AnimalQualifier(AnimalType.DEER)
	private Animal animal;
	public Animal getAnimal() {
		return animal;
	}
} 
SpringDemo.java
package com.concretepage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.concretepage.bean.AnimalService;
public class SpringDemo {
	public static void main(String[] args)  {
	    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
	    ctx.register(AppConfig.class);
	    ctx.refresh();
	    AnimalService animal = ctx.getBean(AnimalService.class);
	    animal.getAnimal().printName();
    	    ctx.close();
	}
}  
Find the output.
---  Deer  --- 


Custom Qualifier without any method using XML

Custom qualifier can also be created without any method, too. For the demo, we have created custom qualifiers @FoxQualifier and @DeerQualifier without any method declaration. In our service class, the constructor argument has been marked with custom qualifier annotation with @Autowired.
DeerQualifier.java
package com.concretepage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Qualifier;
@Target({ElementType.FIELD, ElementType.METHOD,
        ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface DeerQualifier {
} 
FoxQualifier.java
package com.concretepage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Qualifier;
@Target({ElementType.FIELD, ElementType.METHOD,
        ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface FoxQualifier {
} 
AnimalService.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.concretepage.FoxQualifier;
@Service
public class AnimalService {
	private Animal animal;
	@Autowired
	public AnimalService(@FoxQualifier Animal animal){
		this.animal = animal;
	}
	public Animal getAnimal() {
		return animal;
	}
} 
app-conf.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">

		<context:annotation-config/>
		<bean class="com.concretepage.bean.AnimalService"/>
		<bean class="com.concretepage.bean.Fox">
			<qualifier type="FoxQualifier"/>
		</bean>		
		<bean class="com.concretepage.bean.Deer">
			<qualifier type="DeerQualifier"/>
		</bean>
</beans> 
Animal.java
package com.concretepage.bean;
public interface Animal {
	void printName();
} 
Deer.java
package com.concretepage.bean;
public class Deer implements Animal {
	@Override
	public void printName() {
		System.out.println("---  Deer  ---");
	}
} 
Fox.java
package com.concretepage.bean;
public class Fox implements Animal {
	@Override
	public void printName() {
		System.out.println("---  Fox  ---");
	}
} 
SpringDemo.java
package com.concretepage;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.concretepage.bean.AnimalService;
public class SpringDemo {
	public static void main(String[] args) {
		AbstractApplicationContext  context = new ClassPathXmlApplicationContext("app-conf.xml");
		AnimalService service = context.getBean(AnimalService.class);
		service.getAnimal().printName();
		context.close();
	}
} 
Find the output.
---  Fox  ---
 

Reference

Spring Qualifier

Download Complete Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us