首页 > 解决方案 > 为什么 Weld 需要 AnnotationLiteral 而不是 Annotation 类?

问题描述

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

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

RandomQualifier.class我想知道,它不在这里的原因是什么?

有什么理由,为什么他们需要文字的实例而不仅仅是类?

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

标签: javaannotationscdiweld

解决方案


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

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

@interface RandomQualifier {
    int randomNumber();
}

你可以有

class RandomQualifierImpl implements RandomQualifier {

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

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

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

为方便起见,CDI 框架AnnotationLiteral作为帮助类提供了annotationType()使用类型标记“hack”的实现。

这样,您可以简单地编写

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

RandomQualifierImplselect.

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

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

推荐阅读