如何在注释处理中引用方法的实现?

How can I refer to implementations of a method in annotation processing?

我正在尝试 Java (javax) 注释处理。

假设我有一个方法注释:

@Target(ElementType.METHOD)
public @interface MethodAnnotation { }

现在我想处理所有被带有注释方法的类型覆盖的方法:

interface MyInterface() {
    @MethodAnnotation
    void f()
}

class MyClass implements MyInterface {
    override void f() { } // <- I want to process this method
}

@Inherited元注释似乎不适合这里:

Note that this meta-annotation type has no effect if the annotated type is used to annotate anything other than a class.

此外,是否可以处理未在子class 中覆盖的继承class 方法?像这样:

class MyClass {
    @MethodAnnotation
    void f() { }
}

class MySubClass extends MyClass { } // <- I want to process its f()
                                     //    or at least to find out that it doesn't
                                     //    override the method

如何访问 AbstractProcessor 中某个方法的覆盖方法?

我想,要实现这个我需要找到 eclosing class 的子classes,但我也没有找到办法做到这一点。

UPD:我想使用 RoundEnvironment.getRootElements() 是可能的,但仍然没有找到合适的方法。

如果这些注释在运行时可用,并且您想在运行时访问它们,则可以使用 Reflections 库。

例如:

Collection<URL> urls = ClasspathHelper.forPackage("nl.shopname.location.domain");

Reflections reflections = new Reflections(
    new ConfigurationBuilder().setUrls(urls).setScanners(new FieldAnnotationsScanner()));

Set<Field> fieldsWithAnnotation = reflections.getFieldsAnnotatedWith(MyAnnotation.class); 

根据 Jsr269-1.8javax.annotation.processing.Processor 的 javadoc

An annotation is present if it meets the definition of being present given in AnnotatedConstruct. In brief, an annotation is considered present for the purposes of discovery if it is directly present or present via inheritance. An annotation is not considered present by virtue of being wrapped by a container annotation...

AnnotatedConstruct#getAnnotationsByType says that it returns indirectly present annotations, so I think you should scan for methods and check if they indirectly have the annotation using this call. Something in the spirit of this 的 JavaDoc。

免责声明...没试过 ;)

方法注释不被继承。可以通过使用“@Inherited”注解来继承类型注解。

你可以做的是定义一个带有继承类型注释的功能接口,但我不知道这对你来说是否足够优雅。

简短的回答是开箱即用的注释处理不会让您轻松做到这一点,但可以完成。

您实际上必须处理 每个 方法并自己进行过滤,而不是使用正常的调度机制进行处理。

第 1 步:

定义您的处理器,使其 supports all annotations 使用 "*" 作为其支持的注释类型。这意味着您的处理器将在每一轮都被调用。

第 2 步:

每轮使用getRootElements得到整套元素

第 3 步:

创建一个ElementScanner8来遍历你找到的任何元素来寻找ExecutableElements。如果您愿意相信被覆盖的方法带有 @Override 注释,您可以对这些方法进行快速过滤。否则,就全部看看吧。

第 4 步:

现在您需要查看该方法是否覆盖了带有您要查找的注释的方法。没有简单的方法来获取给定方法已覆盖的方法,因此您需要获取 enclosing element of the method, look at its superclass and implemented interfaces (recursively), get their enclosed elements, filter out the methods, and test to see if it has been overridden by the method in question. If it has, you can check the annotations 以查看它是否有您关心的方法。

第 5 步:

此时,您应该已经拥有了您正在寻找的覆盖方法、被覆盖方法和注释镜像,因此您应该能够实现您想要的任何逻辑。