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.