2012年07月29日

eclipseでカスタムアノテーションを作るためのメモ

Javaでカスタムアノテーションを作る際に少し苦労したのでポイントをメモしておく。

まず、アノテーション処理の方法だが、Java1.5の頃からあった「apt (Annotation Processing Tool)」ではなく、1.6から追加された「Pluggable Annotation Processing API」を使用してみた。
細部のプログラミング方法は異なるが(ただ片方理解していれば十分応用できる範囲)、eclipseで作ってデバックして利用するためのポイントはほとんど同じなので、参考にして欲しい。

おおまかな手順はこんな感じだ。
1.アノテーション用のプロジェクトを作ってjarにする。
2.アノテーションを使いたいプロジェクトからjarへClasspathを通す。
3.アノテーションを使いたいプロジェクトのプロパティで「注釈処理」→「ファクトリパス」の設定を行う。

尚、今回は「@SampleAnno」というマーカーアノテーションを作成してみた。
詳細なプログラミング方法はこちらの連載記事が非常にわかりやすいので、本気で作ってみようと考えている方はまず目を通して欲しい。
「Java SE 6完全攻略」第94回 アノテーションを処理する

1.
マーカーアノテーションの宣言:SampleAnno.java
package jp.mitusruog.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface SampleAnno {}

つぎに、アノテーションを処理するProcesser部分:SampleAnnoProcessor.java
package jp.mitusruog.annotation.processor;

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.ElementScanner6;
import javax.tools.Diagnostic.Kind;

import jp.mitusruog.annotation.SampleAnno;

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("jp.mitusruog.annotation.SampleAnno")
public class SampleAnnoProcessor extends AbstractProcessor {

  private Filer filer;
  private Messager messager;

  @Override
  public boolean process(Set annotations,
      RoundEnvironment roundEnvironment) {

    filer = processingEnv.getFiler();
    messager = processingEnv.getMessager();

    class SampleAnnoScanner extends ElementScanner6<Void, Void>{

      /**
       * Type要素(Classとか)についてのアノテーション処理
       */
      @Override
      public Void visitType(TypeElement elem, Void p) {
        if(elem.getAnnotation(SampleAnno.class) != null){
          messager.printMessage(Kind.NOTE, "visitType:" + elem);
        }
        return super.visitType(elem, p);
      }

      /**
       * 変数要素についてのアノテーション処理
       */
      @Override
      public Void visitVariable(VariableElement elem, Void p) {
        messager.printMessage(Kind.NOTE, "variable:" + elem, elem);
        return super.visitVariable(elem, p);
      }
    }

    //Scannerの作成
    SampleAnnoScanner scanner = new SampleAnnoScanner();
    for (Element element : roundEnvironment.getRootElements()) {
      //Root要素から順にScan
      scanner.scan(element);
    }
    return true;
  }
}

次がMETA-INFの設定で(実はここが一番苦労したポイントだった)、下のようなフォルダ構成(「src」がコンテキストルート)の場合、その直下に「META-INF」フォルダを作成して、その中に「javax.annotation.processing.Processor」ファイルを作成する。

フォルダ構成
src
 ├jp(→ここにソースファイルが入る)
 └META-INF
  └services
   └javax.annotation.processing.Processor

javax.annotation.processing.Processorファイル
jp.mitusruog.annotation.processor.SampleAnnoProcessor

ファイルの中には上で作成したProcessorクラスのFQNを設定する。

で、ここまで準備できたら、eclipseのエクスポート機能か何かでjarを作って1.の手順は完了。
2.
jarにclasspathを通すところはたぶん知っていると思うので割愛。
3.

eclipseのプロジェクトのプロパティを開いて
「Javaコンパイラ→注釈処理→ファクトリー・パス」まで行ったら、右側の「Jarの追加(もしくは外部Jarの追加)」で先ほど作成したjarを追加する。

20120729_01.jpg

アノテーションを利用する側のソース:Sample5.java
import java.util.Date;
import jp.mitusruog.annotation.SampleAnno;

@SampleAnno
public class Sample5 {
  private int no;
  private String name;
  private String address;
  private Date date;
}

ここで、「@」を入力した後に「Ctl+スペース」で入力補完のリストを表示させてみて「@SampleAnno」が候補としてあがってない場合は、「javax.annotation.processing.Processor」ファイルの内容が正しくない可能性が高いので再度確認して欲しい。

デバックについてはAptina Unitが良さそう。
まだ十分に使ってないので、なんとも言えないがassertが親切だったた結構使えると思う。

Javaの最新記事

posted by mitsuruog at 00:14 | Comment(0) | TrackBack(0) | Java | |
この記事へのコメント
コメントを書く
認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。