6

次のカスタム Java アノテーションの場合

@CustomAnnotation(clazz=SomeClass.class)
public class MyApplicationCode
{ 
   ... 
}

私は基本的に、コンパイル時に MyApplicationCode の Class オブジェクトと clazz パラメータの両方を取得して、コーディング規約の一貫性を確認できるようにしたいと考えています (別の話です)。基本的に、注釈プロセッサで MyApplicationCode.class および Someclass.class コードにアクセスできるようにしたいと考えています。私はほとんどそこにいますが、何かが欠けています。私は持っている

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface CustomAnnotation
{
   public Class clazz();
}

それから私はプロセッサのために持っています:

public class CustomAnnotationProcessor extends AbstractProcessor
{
    private ProcessingEnvironment processingEnvironment;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment)
    {
        this.processingEnvironment = processingEnvironment;
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment)    
    {
        Set<? extends Element> elements = environment.getElementsAnnotatedWith(ActionCommand.class);

        for(Element e : elements)
        {
            Annotation annotation = e.getAnnotation(CustomAnnotation.class);
            Class clazz = ((CustomAnnotation)annotation).clazz();        

            // How do I get the actual CustomAnnotation clazz?
            // When I try to do clazz.getName() I get the following ERROR:
            // Attempt to access Class object for TypeMirror SomeClass

            // Also, how do I get the Class object for the class that has the annotation within it?
            // In other words, how do I get MyApplicationCode.class?
        }
    }
}

したがって、process メソッドで実行しようとしているのは、以下の元のコードから SomeClass.class と MyApplication.class を取得して、コンパイル時にカスタム検証を行うことです。私は一生、これらの2つの値を取得する方法を理解できないようです...

@CustomAnnotation(clazz=SomeClass.class)
public class MyApplicationCode

更新:次の投稿には、さらに多くの詳細があり、さらに詳しくなっています。しかし、問題は、クラス オブジェクトをプルする TypeMirror オブジェクトが得られることです。これについては説明していません。 -from-annotations-in-an-annotationprocessor/

Update2: 次のようにして MyApplication.class を取得できます

String classname = ((TypeElement)e).getQualifiedName().toString();
4

3 に答える 3

1

ブログhttp://blog.retep.org/2009/02/13/getting-class-values-from-annotations-in-an-annotationprocessor/の方向にあなたを向けるつもりでしたが、あなたのように見えますすでにそれを見つけました。

MyApplication Elementにアクセスする方法を理解しているので、それについては説明しません。

表示される例外には、実際にはその中に注釈プロパティのタイプが含まれています。したがって、例外をキャッチしたときにアノテーションclazz値を参照できます。

public class CustomAnnotationProcessor extends AbstractProcessor
{
    private ProcessingEnvironment processingEnvironment;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment)
    {
        this.processingEnvironment = processingEnvironment;
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment)    
    {
        Set<? extends Element> elements = environment.getElementsAnnotatedWith(ActionCommand.class);

        for(Element e : elements)
        {
            CustomAnnotation annotation = e.getAnnotation(CustomAnnotation.class);    

            TypeMirror clazzType = null;
            try {
                annotation.clazz();
            } catch (MirroredTypeException mte) {
                clazzType = mte.getTypeMirror();
            }

            System.out.println(clazzType); // should print out SomeClass

        }
    }
}

はい、これはソリューションの完全なハックであり、API開発者がアノテーションプロセッサ機能を使用してこの方向に進むことを決定した理由はわかりません。しかし、私は多くの人がこれを実装しているのを見てきました(を含む)、そして言及された記事はこのテクニックも説明しています。これは現時点では許容できる解決策のようです。

MyApplicationCodeとSomeClassのクラス値を「取得」するという点では、コンパイル中のクラスの場合は取得できません。ただし、ElementおよびTypeMirror表現を使用して、クラス(メソッド、フィールド、クラス名、存在するアノテーションなど)に対して高レベルの検証を実行できます。

于 2012-06-15T14:49:04.173 に答える
0

この関連する SO の質問を読んだ後、Java Annotation Processing Tool (APT) に関するこの優れたページを見つけました。2005年のものなので、最近はこれを行う最良の方法ではないかもしれません.

APT [...] は Java の注釈処理ツールです。より具体的には、APT を使用すると、コードのコンパイル中にソース ファイル内の注釈を処理するコードをプラグインできます。そのプロセスでは、メモ、警告、およびエラーを出力できます。

これは Oracle の JDK 専用です。

于 2012-05-19T09:47:38.060 に答える
-1

コンパイル時間です。コンパイラはソースコードのコンパイルさえ完了していないと思います。このような情報を AnnotatedElement インスタンスから取得すると、注釈を付けたタイプの関連情報が得られますが、関連するクラス ファイルがまだ仮想マシンによってロードされていないため、まだ利用できないランタイム プロパティは得られません。また、Java の仮想マシンでコンパイラが実行されることさえ保証されていないため、クラス ファイルをロードできるようにする必要はありません。その要件は、特定の仮想マシンが読み取ることができるバイトコードを生成できることだけです。

したがって、ミラー Api を確認し、注釈を付けたクラス/メソッド/フィールドに関する関連情報については、そのインスタンスを表す AnnotatedElement を確認してください。

余談ですが、これはあくまで私が推測した情報なので、真実ではないかもしれません。

于 2012-05-18T23:01:17.590 に答える