I just tried to retrieve an object from CDI with a Qualifier.
private static class QualifierLiteral
extends AnnotationLiteral<RandomQualifier>
implements RandomQualifier {
}
QualifierLiteral QUALIFIER = new QualifierLiteral();
CDI.current().select(TranslationProvider.class, QUALIFIER).get()
I wonder, whats the reason why its not RandomQualifier.class
here?
Is there any reason, why they need the instance of a literal instead of just the class?
(Scope of the question is to learn something about the inner workings of weld/cdi/java)
Weld supports qualifiers with members (the annotation elements). If you could only pass Class
arguments, it wouldn't be able to do that. Instead, select
expects an annotation instance that can provide expected values for those members.
Remember that annotation types are just interfaces. So you can create subclasses for them and instantiate those. For example, assume your RandomQualifier
looked like
@interface RandomQualifier {
int randomNumber();
}
You could have
class RandomQualifierImpl implements RandomQualifier {
@Override
public Class<? extends Annotation> annotationType() {
return RandomQualifier.class;
}
@Override
public int randomNumber() {
return 4;
}
}
Normally, when you annotate a class (or anything else) with your annotation and use reflection to extract that annotation, the JVM is responsible for creating a dynamic subclass that implements those methods and returning a corresponding instance. But here, we have to do it ourselves.
For convenience, the CDI framework provides AnnotationLiteral
, as a helper class, to provide the implementation of annotationType()
using the type token "hack".
This way, you can simply write
class RandomQualifierImpl extends AnnotationLiteral<RandomQualifier> implements RandomQualifier {
@Override
public int randomNumber() {
return 4;
}
}
and provide a new RandomQualifierImpl
instance to select
.
Or, if you don't need annotation elements (members) at all, use an anonymous subclass
Annotation instance = new AnnotationLiteral<RandomQualifier>() {};