获取注释处理器中生成的注释的所有值

问题描述 投票:1回答:2

我有一个用生成的注释注释的VariableElement字段(这就是为什么我不能使用field.getAnnotation(annotationClass))。我需要将所有参数传递给此注释。

请注意,通过“生成的注释”,我的意思是注释处理器生成了注释类本身(不是带注释的注释类)。正在注释的字段/类位于手写源代码中。

它看起来并不那么难,到目前为止我已经想到了这个:

for (AnnotationMirror annotation : field.getAnnotationMirrors()) {
    Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValueMap = annotation.getElementValues();

    messager.printMessage(Diagnostic.Kind.WARNING, annotation.toString() + ":" + annotationValueMap.toString());
}

我以为这会做到,但该字段的输出如下:

@MyAnnotation:{}

因此,处理器确实识别该字段已注释,但我无法访问传递的参数。即使该字段是定义注释的,并且使用注释传递参数(必须,因为注释定义了所需的参数而没有默认值):

@MyAnnotation(max = 387, min = 66876, ...)
private Integer myField;

这是生成的注释代码:

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
  int max();

  boolean allowAuto();

  int min();
}

我已经多次清理编译项目,处理器永远不会看到值。我在这里俯瞰什么?处理器显然可以看到注释本身,但传递给它的参数是隐藏的。

java annotations annotation-processing
2个回答
2
投票

回想一下,注释处理器作为编译器的一部分运行,称为“回合”。此过程以迭代方式运行,直到没有新的代码进行编译,然后处理器获得最后一次运行的机会(对于此答案不是必需的,但对于更多上下文有帮助)。每轮只将新创建的类型直接提供给处理器进行检查。

这里似乎发生的是,在一轮中你发出了一个新的注释类型,它应该允许处理器观察某些提交编译的代码的某些特征。但是,在给定轮次中创建的任何类型在下一轮开始之前尚未编译。

对于这个问题,我们在这里遇到了冲突 - 编译了一些使用尚不存在的注释的Java源代码。处理器首先创建注释,然后尝试从这些部分编译的源中读取新创建的注释。不幸的是,在编译注释之前,我们实际上无法读取注释。相反,我们需要等到后续轮次(一旦注释本身已经编译),然后返回到已经完成编译并检查它的那个类。

这可以自己实现而不会有太多麻烦,但最简单的方法通常是依靠google / auto项目(特别是自动公共库,请参阅https://github.com/google/auto/tree/master/common),并扩展他们的BasicAnnotationProcessor类。它支持的一个很好的功能是自动检查类型并检查是否存在任何编译问题 - 如果是,它们将推迟到下一轮,以便您可以处理它们而不会出现任何类型解析问题。


1
投票

使用VariableElement提供的getAnnotation(MyAnnotation.class)

在您的示例代码中,您可以执行此操作以获取minmax参数

MyAnnotation myAnnotation= field.getAnnotation(MyAnnotation.class);
int max = myAnnotation.max();
int min = myAnnotation.min();

这将起作用,除非注释成员返回class/class[]值,如果您尝试使用此方法获取值,将在该值中获得异常。

有关如何获取类文字值的更多信息,请参阅此答案

How to read a Class[] values from a nested annotation in an annotation processor

或者使用注释镜像

for (AnnotationMirror annotation : field.getAnnotationMirrors()) {
    Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValueMap = annotation.getElementValues();
    annotationValueMap.forEach((element, annotationValue) -> {
        messager.printMessage(Diagnostic.Kind.WARNING, element.getSimpleName().toString() + ":" + annotationValue.getValue());
    });
}

如果您在该字段上有多个注释,则可以迭代注释镜像并使用检查types.isSameType(annotationMirror.getAnnotationType(), elements.getTypeElement(MyAnnotation.class.getName()).asType())查找您感兴趣的注释

© www.soinside.com 2019 - 2024. All rights reserved.