为什么 Weld 需要 AnnotationLiteral 而不是 Annotation class?

Why does Weld need a AnnotationLiteral instead just of the Annotation class?

我刚刚尝试使用限定符从 CDI 检索对象。

private static class QualifierLiteral
        extends AnnotationLiteral<RandomQualifier>
        implements RandomQualifier {
}
QualifierLiteral QUALIFIER = new QualifierLiteral();
CDI.current().select(TranslationProvider.class, QUALIFIER).get()

我想知道,这里没有RandomQualifier.class是什么原因?

有什么理由,为什么他们需要文字实例而不只是 class?

(问题范围是了解weld/cdi/java的内部工作原理)

Weld 支持 qualifiers with members(注释元素)。如果您只能传递 Class 个参数,它就无法做到这一点。相反,select 需要一个可以为这些成员提供预期值的注释实例。

请记住,注释类型只是接口。所以你可以为它们创建 subclasses 并实例化它们。例如,假设您的 RandomQualifier 看起来像

@interface RandomQualifier {
    int randomNumber();
}

你可以

class RandomQualifierImpl implements RandomQualifier {

    @Override
    public Class<? extends Annotation> annotationType() {
        return RandomQualifier.class;
    }

    @Override
    public int randomNumber() {
        return 4;
    }
}

通常,当您使用注释对 class(或其他任何内容)进行注释并使用反射提取该注释时,JVM 负责创建实现这些方法的动态子class并返回相应的实例。但是在这里,我们必须自己做。

For convenience, the CDI framework provides AnnotationLiteral, as a helper class, to provide the implementation of annotationType() using the type token "hack".

这样,你可以简单地写

class RandomQualifierImpl extends AnnotationLiteral<RandomQualifier> implements RandomQualifier {
    @Override
    public int randomNumber() {
        return 4;
    }
}

并向 select 提供一个新的 RandomQualifierImpl 实例。

或者,如果您根本不需要注释元素(成员),请使用匿名子class

Annotation instance = new AnnotationLiteral<RandomQualifier>() {};