3

JDK 6 および 7 の Java Annotation Processing API (5 の apt ツール API ではない) は、アノテーション プロセッサのライフサイクルを定義します。1 つは引数のないコンストラクターを介してインスタンス化され、initメソッドはインスタンスで呼び出され、ProcessingEnvironmentそのプロセッサがメソッドを介して使用されprocessます。プロセッサの 1 つのインスタンスのみが作成され、該当する場合、後続のすべての処理ラウンドで使用されます。

私のプロセッサー・クラスは少し肥大化していたので、処理するはずの別個のアノテーション用のハンドラー・クラスを作成しました。これらのクラスのメソッドでは、ユーティリティ メソッド用にから取得したインスタンスを常に渡してElementsいます。これにより、メソッドのシグネチャがかなり長くなります。TypesProcessingEnvironment

プロセッサ インスタンスだけでなく、ハンドラでもインスタンスElementsへの参照を維持したいだけです。渡されたTypesものからメソッドに取得することでこれを行いました。さて、これは安全かどうか疑問に思っています。JavaDoc forは、一部のメソッドがプロセッサに対して 1 回だけ呼び出されることを明確にしていますが、ここでは言及されていません。これは暗黙のうちに理解されていると思い込んでいましたが、100%確実ではありません。ProcessingEnvironmentinitProcessorinit

Messager同様に取得できるインスタンスが、ProcessingEnvironmentすべての処理ラウンドで同じままであるかどうかも知りたいです。あるラウンドからの警告/エラーが表示されるのではなく、他のラウンドが取り残されることは望ましくありません。ラウンド全体で同じインスタンスを使用しても安全であると合理的に確信していますが、ある程度の確実性が必要です。

4

2 に答える 2

2

私は同じ質問を自問し、現在のラウンドのProcessingEnvironmentが提供するユーティリティを常に使用することにしましたinitjavacを使用しても違いはないように見えますが、異なる動作を示す可能性のある他の注釈処理ツールがあります。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 に答える