【问题标题】:Java AnnotationProcessing - Get fields of the AnnotationJava AnnotationProcessing - 获取注解的字段
【发布时间】:2017-08-30 16:31:26
【问题描述】:

根据 API AnnotationProcessing,我有一个问题。 这是一个小例子。

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface MyAnnotation
{
   String strNumberOne() default "";

   String strNumberTwo() default "";

   String strNumberThree() default "";
}


public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
    // I do not know how to beginn here
      return true;
   }
}

public class MyClass
{
   @MyAnnotation(strNumberOne="one", strNumberTwo= "two")
   private String strARandomString;
}

现在我想读取注释中声明的字段,如果有未声明的字段,我的程序应该采用默认值。

我想将值写入列表。最后我的列表应该是这样的:

LinkedList<String> s = new LinkedList<>();
s.add(strNumberOne); // "one"
s.add(strNumberTwo); // "two"
s.add(strNumberThree); // (default) ""

我该怎么做?我找到了一种可以提供帮助的方法。在接口“元素”中,方法名称是“getElementValuesWithDefaults()”。但是不知道怎么用。。 另外我想知道 TypeElement 和 Element 有什么区别。 我感谢每一个答案! :)

最好的问候!

【问题讨论】:

    标签: java annotations annotation-processing


    【解决方案1】:

    如果MyAnnotation 是您的处理器支持的注释,那么您只需编写如下内容:

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment           env) {
        if (shouldClaim(annotations)) {
            for (Element e : env.getElementsAnnotatedWith(MyAnnotation.class)) {
                MyAnnotation a = e.getAnnotation(MyAnnotation.class);
    
                String str1 = a.strNumberOne();
                String str2 = a.strNumberTwo();
                String str3 = a.strNumberThree();
                // Add them to a List or whatever you need.
            }
    
            return true;
        }
        return false;
    }
    
    private boolean shouldClaim(Set<? extends TypeElement> annotations) {
        Set<String> supported = getSupportedAnnotationTypes();
        for (TypeElement a : annotations) {
            if (supported.contains(a.getQualifiedName().toString()))
                return true;
        }
        return false;
    }
    

    shouldClaim 方法的逻辑由process 的文档解释。如果您的注释支持例如,它会更复杂。 *name.* 形式的类型,但一般情况下您不会。 (有关这些含义的描述,请参阅 getSupportedAnnotationTypes。)

    如果MyAnnotation不是你的处理器支持的注解,那么你需要通过getElementValuesWithDefaults如果它是在您正在编译的包中声明的类型。因为注解处理发生在编译期间,正在编译的源文件尚不存在类文件,这就是我们改用Element API 的原因。

    Element 表示某种声明,例如类、方法或变量。 TypeElement 表示类、接口、枚举或注解类型声明。 TypeElementClass 的用途相似,只是我们可以将 TypeElement 用于不一定要编译的类。

    要通过元素 API 获取注释值,您需要执行以下操作:

    Elements    elements     = processingEnv.getElementUtils();
    TypeElement myAnnotation = elements.getTypeElement("com.example.MyAnnotation");
    
    for (Element e : env.getElementsAnnotatedWith(myAnnotation)) {
        for (AnnotationMirror mirror : e.getAnnotationMirrors()) {
            DeclaredType annotationType = mirror.getAnnotationType();
            Element      annotationDecl = annotationType.asElement();
    
            if (myAnnotation.equals(annotationDecl)) {
                Map<? extends ExecutableElement, ? extends AnnotationValue> values =
                    elements.getAnnotationValuesWithDefaults(mirror);
    
                String str1 = (String) getValue(values, "strNumberOne");
                String str2 = (String) getValue(values, "strNumberTwo");
                String str3 = (String) getValue(values, "strNumberThree");
                // ...
            }
        }
    }
    
    private Object getValue(Map<? extends ExecutableElement,
                                ? extends AnnotationValue> values,
                            String name) {
        for (Map.Entry<? extends ExecutableElement,
                       ? extends AnnotationValue> e : values.entrySet()) {
            if (name.contentEquals(e.getKey().getSimpleName()))
                return e.getValue().getValue();
        }
        return null;
    }
    

    这很痛苦,但我们只需要使用元素 API如果我们感兴趣的注解是正在编译的类之一。

    我们可能还想找到AnnotationMirror 和/或AnnotationValue 以使用Messager.printMessage 重载之一在特定元素上生成某种消息,该重载将上述对象之一作为参数。

    【讨论】:

      猜你喜欢
      • 2013-07-13
      • 2020-05-13
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多