16

メソッドを持つ2つのクラスがあり、2つのクラスのメソッドを1つのクラスに結合したいと思います。

@Service("ITestService")
public interface ITest1
{
   @Export
   void method1();
}

@Service("ITestService")
public interface ITest2
{
   @Export
   void method2();
}

結果は次のようになります。

public interface ITestService extends Remote
{
  void method1();
  void method2();
}

AnnotationProcessorを最初に実行すると、正しい出力が生成されます(RoundEnvironmentには両方のクラスが含まれているため)。

しかし、クラスの1つを編集した場合(たとえば、新しいメソッドを追加した場合)、RoundEnviromentには編集されたクラスのみが含まれるため、結果は次のようになります(インターフェイスITest1にnewMethod()を追加します)

public interface ITestService extends Remote
{
  void method1();
  void newMethod();
}

現在、method2がありません。問題を解決する方法がわかりません。プロジェクト内のすべてのクラスにアクセスする方法(環境)はありますか?または、これを解決する別の方法はありますか?

クラスを生成するコードはかなり長いので、ここでクラスを生成する方法について簡単に説明します。要素を繰り返し処理してenv.getElementsAnnotatedWith(Service.class)メソッドを抽出し、次のコマンドを使用して新しいファイルに書き込みます。

FileObject file = null;
file = filer.createSourceFile("com/test/" + serviceName);
file.openWriter().append(serviceContent).close();
4

2 に答える 2

3

NetBeans @Messagesアノテーションは、同じパッケージ内のすべてのクラスごとに 1つのBundle.javaファイルを生成します。注釈プロセッサの次のトリックのおかげで、インクリメンタル コンパイルで正しく動作します。

Set<Element> toProcess = new HashSet<Element>();
for (Element e : roundEnv.getElementsAnnotatedWith(Messages.class)) {
  PackageElement pkg = findPkg(e);
  for (Element elem : pkg.getEnclosingElements()) {
    if (elem.getAnnotation(Message.class) != null) {
      toProcess.add(elem);
    }
  }
}
// now process all package elements in toProcess 
// rather just those provided by the roundEnv

PackageElement findPkg(Element e) {
  for (;;) {
    if (e instanceof PackageElement) {
      return (PackageElement)e;
    }
    e = e.getEnclosingElement();
  }
}

これを行うことで、コンパイルがパッケージ内の単一のソース ファイルに対してのみ呼び出された場合でも、パッケージ内のすべての (最上位の) 要素が一緒に処理されることを確認できます。

注釈 (パッケージ内の最上位の要素、またはパッケージ内の任意の要素) を探す場所がわかっている場合は、そのようなすべての要素のリストを常に取得できるはずです。

于 2015-08-02T07:30:12.647 に答える