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

时间:2016-07-10 12:58:51

标签: java 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元注释似乎不适用于此:

  

请注意,如果使用带注释的类型来注释除类之外的任何内容,则此元注释类型无效。

此外,是否可以处理未在子类中重写的继承类方法?像这样:

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类的子类,但我还没有找到一种方法来实现这一点。

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

4 个答案:

答案 0 :(得分:5)

简短的回答是,开箱即用的注释处理并不能让您轻松完成,但可以完成。

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

第1步:

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

第2步:

使用getRootElements每周获取整个元素集。

第3步:

创建ElementScanner8以遍历您找到的查找ExecutableElement的任何元素。如果您愿意相信已使用@Override注释了重写方法,则可以对这些方法进行快速过滤。否则,只要看看所有这些。

第4步:

现在您需要查看该方法是否使用您正在寻找的注释覆盖方法。获取给定方法已覆盖的方法并不容易,因此您需要获取方法的enclosing element,查看其superclassimplemented interfaces(递归) ,通过相关方法获取enclosed elementsfilter out the methodstest to see if it has been overridden。如果有,您可以查看annotations,看看它是否有您关心的。

第5步:

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

答案 1 :(得分:2)

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

  

如果注释符合存在的定义,则存在注释   在AnnotatedConstruct中给出。简而言之,考虑注释   出于发现的目的而存在,如果它直接存在或   通过继承呈现。注释不被视为存在   被容器注释包裹的好处......

AnnotatedConstruct#getAnnotationsByType的JavaDoc表示它会间接返回当前注释,因此我认为您应该扫描方法并检查它们是否使用此调用间接地具有注释。符合this精神的东西。

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

答案 2 :(得分:2)

不继承方法注释。可以通过使用&#34; @ Inherited&#34;继承类型注释。注释

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

答案 3 :(得分:1)

如果这些注释在运行时可用,并且您希望在运行时访问它们,则可以使用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);