3

JDK 6 和 7 中的 Java 注释处理 API(不是 5 中的 apt 工具 API)定义了注释处理器的生命周期。一个是通过无参数构造函数实例化的,init使用实例调用该方法ProcessingEnvironment,然后通过该process方法使用该处理器。如果适用,在所有后续处理轮次中只制作和使用一个处理器实例。

由于我的处理器类变得有点臃肿,我已经为它应该处理的单独注释创建了处理程序类。在这些类的方法中,我总是传入我从它们的实用方法中获得Elements的实例。这使我的方法签名相当长。TypesProcessingEnvironment

我宁愿只在处理程序以及处理器实例中保留对Elementsand实例的引用。Types我通过将它们从ProcessingEnvironment传递到init方法中来做到这一点。现在,我想知道这是否安全。JavaDoc forProcessor清楚地表明,某些方法仅对处理器调用一次,但init此处未提及。我有点假设这是隐含的理解,但我不是 100% 确定。

我还想知道Messager也可以从中获得的实例ProcessingEnvironment在所有处理轮次中是否保持不变。我宁愿没有出现一轮的警告/错误,但其他人却被排除在外。我有理由确定在各轮中使用相同的实例应该是安全的,但只是想要一些确定性。

4

2 回答 2

2

我问过自己同样的问题,并决定始终使用ProcessingEnvironmentinit. 使用javac时似乎没有任何区别,但是还有其他注释处理工具可能会显示不同的行为。我已经体验过 javac 中的处理工具和 eclipse 使用的处理工具之间的一些差异,因此我会非常小心地处理文档中未明确说明的任何内容。问题是,您想测试所有现有的处理工具吗?

另外,我认为如果这些处理辅助工具注定永远不会改变,那么它们将成为处理器构造函数的参数。

于 2011-11-05T21:55:41.703 回答
1

值得一提的是,如果多次调用AbstractProcessor的方法(该类的javadocProcess建议将其作为子类,可以由实现者使用),则会抛出异常。IllegalStateExceptioninit

这并不意味着传递的ProcessingEnvironment不能在后续的 getter 调用或不同的轮次中返回不同的值,尽管它不是常规的。无论如何,在方法的开头可能值得检查process

private ProcessingEnvironment processingEnv;
private Elements elementUtils;
private Types typeUtils;

public Processor() {
}

@Override
public synchronized void init(final ProcessingEnvironment processingEnv) {
    this.processingEnv = processingEnv;
    elementUtils = processingEnv.getElementUtils();
    typeUtils = processingEnv.getTypeUtils();
}

private void checkEnvironmentChange() {
    checkSame(elementUtils, processingEnv.getElementUtils(), "elementUtils");
    checkSame(typeUtils, processingEnv.getTypeUtils(), "typeUtils");
}

private <T> void checkSame(final T object1, final T object2, final String name) {
    if (object1 != object2) {
        throw new IllegalStateException(name + " should not change");
    }
}

@Override
public boolean process(final Set<? extends TypeElement> annotations, 
        final RoundEnvironment roundEnv) {
    checkEnvironmentChange();
    ...
}
于 2012-07-29T22:45:31.683 回答