It's not the @Qualifier
annotation's purpose to use it when getting beans via ApplicationContext. But since you need such or similar functionality for some reasons, I suggest a workaround.
Create @Wanted
and @NotWanted
annotation:
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Wanted {
}
and
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD,
ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotWanted {
}
Annotate your bean classes with these new annotations:
@Component
@NotWanted
public class NotWantedService implements Service {}
and
@Component
@Wanted
public class WantedService implements Service {}
Then you should add 2 methods somewhere where you have access to the ApplicationContext
:
ApplicationContext applicationContext;
private <T> Collection<T> getBeansByTypeAndAnnotation(Class<T> clazz, Class<? extends Annotation> annotationType){
Map<String, T> typedBeans = applicationContext.getBeansOfType(clazz);
Map<String, Object> annotatedBeans = applicationContext.getBeansWithAnnotation(annotationType);
typedBeans.keySet().retainAll(annotatedBeans.keySet());
return typedBeans.values();
}
private <T> Optional<T> getBeanByTypeAndAnnotation(Class<T> clazz, Class<? extends Annotation> annotationType) {
Collection<T> beans = getBeansByTypeAndAnnotation(clazz, annotationType);
return beans.stream().findFirst();
}
And now you can use them to get beans or one bean by annotation and type like this:
Collection<Service> services = getBeansByTypeAndAnnotation(Service.class, Wanted.class);
or
Service service = getBeanByTypeAndAnnotation(Service.class, Wanted.class);
Possibly it's not the best way to deal with the problem. But since we are unable to get beans from ApplicationContext
by qualifier and type 'out of box', that's one of the ways to do this.