Spring Custom Qualifier Annotation
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.
Contents
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(); }
<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>
<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>
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; } }
@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; } }
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; } }
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; } }
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(); } }
Teacher Sudama
Custom Qualifier with value() Method using Java Configuration
Here we will create a custom qualifier withvalue()
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(); }
package com.concretepage; public enum AnimalType { DEER, FOX }
package com.concretepage; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan(basePackages="com.concretepage.bean") public class AppConfig { }
package com.concretepage.bean; public interface Animal { void printName(); }
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 ---"); } }
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 ---"); } }
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; } }
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(); } }
--- 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 { }
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 { }
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; } }
<?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>
package com.concretepage.bean; public interface Animal { void printName(); }
package com.concretepage.bean; public class Deer implements Animal { @Override public void printName() { System.out.println("--- Deer ---"); } }
package com.concretepage.bean; public class Fox implements Animal { @Override public void printName() { System.out.println("--- Fox ---"); } }
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(); } }
--- Fox ---