Creating and Configuring Custom @Qualifier Annotation
When Handling Multiple Dependencies with @Primary or Handling Multiple Dependencies with @Qualifier are not sufficient or you want to create your own custom @Qualifier
Annotations for some reason. Spring allows you to create your own custom @Qualifier annotations.
Creating Custom @Qualifier Annotations
As an example we create a parent @Animal
annotation which other annotations (@DogType
and @CatType
) will inherit from. Just so we don’t have to copy the entire annotation header into the others. But only @DogType
and @CatType
will be usable because we made @Animal
annotation package local.
package com.memorynotfound.spring.core.autowired.annotations;
import org.springframework.beans.factory.annotation.Qualifier;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Animal {
}
This will be a custom qualifier annotation for cats.
package com.memorynotfound.spring.core.autowired.annotations;
@Animal
public @interface CatType {
}
This will be a custom qualifier annotation for dogs.
package com.memorynotfound.spring.core.autowired.annotations;
@Animal
public @interface DogType {
}
Beans
Next we create our beans.
package com.memorynotfound.spring.core.autowired;
public class Animal {
}
The Cat is annotated with the @CatType
annotation.
package com.memorynotfound.spring.core.autowired;
import com.memorynotfound.spring.core.autowired.annotations.CatType;
import org.springframework.stereotype.Component;
@CatType
@Component
public class Cat extends Animal {
@Override
public String toString() {
return "Cat {}";
}
}
The Dog is annotated with the @DogType
annotation.
package com.memorynotfound.spring.core.autowired;
import com.memorynotfound.spring.core.autowired.annotations.DogType;
import org.springframework.stereotype.Component;
@DogType
@Component
public class Dog extends Animal {
@Override
public String toString() {
return "Dog {}";
}
}
Using Custom Qualifiers
Finally we can use our custom @Qualifier annotations. We autowire two types of animal, one of type dog, the other of type cat.
package com.memorynotfound.spring.core.autowired;
import com.memorynotfound.spring.core.autowired.annotations.CatType;
import com.memorynotfound.spring.core.autowired.annotations.DogType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Shepperd {
@Autowired
private @DogType Animal dog;
@Autowired
private @CatType Animal cat;
@Override
public String toString() {
return "Shepperd{" +
"dog=" + dog +
", cat=" + cat +
'}';
}
}
Enable Auto Component Scanning
We enable spring auto component scanning by registering the <context:component-scan/> and providing a package name which will be recursively scanned for components.
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.memorynotfound"/>
</beans>
Testing The Application
We bootstrap the spring application and simply call the toString()
method of the spring managed Shepperd
bean.
package com.memorynotfound.spring.core.autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Run {
public static void main(String... args) {
ApplicationContext xmlContext = new ClassPathXmlApplicationContext("app-config.xml");
Shepperd shepperd = xmlContext.getBean(Shepperd.class);
System.out.println(shepperd);
}
}
The previous code will generate the following output.
Shepperd{dog=Dog {}, cat=Cat {}}
@Qualifier
annotation is sufficient for most cases. But this is a rather ‘just because you can’ story. It could be useful when your application needs more general purpose marker annotations which you can reuse. e.g.: ‘online, offline’.
Hello, your code is incorrect, really your custom qualifier never works. Just do the following: @Autowired private @DogType Animal dog; to @Autowired private @DogType Animal dog_; It appears: An exception occured while executing the Java class. Error creating bean with name 'shepperd': Unsatisfied dependency expressed through field 'dog_'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.memorynotfound.spring.core.autowired.Animal' available: expected single matching bean but found 2: cat,dog -> [Help 1] Your code only works because @Autowired has three resolutions: * By Type, in this case by Animal, Ok, here we have two candidates. * By @Qualifier, in this case you… Read more »