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 {}}
Some Thoughts You can ask yourself the question, is this actually useful? My experience tells me that the normal @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’.

References

Download

You may also like...