【问题标题】:Why does Weld need a AnnotationLiteral instead just of the Annotation class?为什么 Weld 需要 AnnotationLiteral 而不是 Annotation 类?
【发布时间】:2020-06-22 17:09:22
【问题描述】:

我刚刚尝试使用限定符从 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的内部工作原理)

【问题讨论】:

    标签: java annotations cdi weld


    【解决方案1】:

    Weld 支持qualifiers with members(注释元素)。如果你只能传递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 负责创建实现这些方法的动态子类并返回相应的实例。但在这里,我们必须自己做。

    For convenience,CDI 框架提供AnnotationLiteral,作为帮助类,使用type token "hack" 提供annotationType() 的实现。

    这样,你可以简单地写

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-09-25
      • 1970-01-01
      • 2018-03-18
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      相关资源
      最近更新 更多