注釈プロセッサへのプローブ
プロジェクトには、ロンボクと呼ばれる非常に便利なプラグインがあります。このプラグインは、javabeanを生成するために使用できるいくつかの簡単な注釈と、開発の効率を向上させ、開発時間を節約するいくつかのゲッター/セッターメソッドを提供します。
今日、この操作を実現するためにlombokが使用する方法を見てみましょう。実際、lombokはjdk1.5で追加された新機能である注釈プロセッサを使用しています。@ Getterは単なる注釈であり、実際の処理部分
は注釈プロセッサにあります内部で実現した公式リファレンスリンク。
背景紹介
注釈プロセッサの完全な名前は、実際にはプラグイン可能な注釈プロセッサであるPluggable Annotation Processing APIです。これは、JSR269提案の実装です。詳細については、リンク、JSR269リンクのコンテンツを参照してください。
どのように機能するか?次の図を参照してください
。1。解析して入力:解析して入力すると、Javaコンパイラーがソースコードを解析して、
この段階でAST(抽象構文分析ツリー)を生成します2.注釈処理:注釈プロセッサ段階、注釈プロセッサがこの時点で呼び出され、コードをこの時点で検証できます、新しいファイルなどを生成します(処理後の最初のステップに循環できます)
3.分析と生成:分析して生成します。この時点で、最初の2つのステップが完了した後、バイトコードを生成します(タイプの消去など、この段階で砂糖を理解します)。
これらは実際には、それがどのように実装されているかについて表面的な印象を皆に与えるためのものです。
練習
上記の情報を読んだ後、あなたはあなたの脳に一般的な印象を持っているはずです。さあ、簡単な例を書いてそれを練習しましょう。
注釈プロセッサを使用するには、2つのステップが必要です:
1.注釈をカスタマイズする
2. AbstractProcessorを継承するそして、プロセスメソッドを実装します
@InterfaceAnnotationをクラスに追加し、コンパイル時に "I" +クラス名のインターフェイスクラスを生成するという非常に簡単な例を書いてみましょう。
まず、2つのモジュールを定義します。アノテーションとハンドラー。もう1つはアノテーションの呼び出しに使用されます。
ステップ1:注釈をカスタマイズする
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface InterfaceAnnotation {
}
1. @ Target:このアノテーションが何で使用されているかを示します。ここでElementType.TYPEは、クラスでのアノテーションの使用を指します
。2。@ Retention:保持の段階を示します。ここで、RetentionPolicy.SOURCEはソースコードの段階です。コンパイルします。後者のクラスにはそのような注釈はありません
ステップ2:AbstractProcessorを継承し、プロセスメソッドを実装する
@SupportedAnnotationTypes(value = {"com.example.processor.InterfaceAnnotation"})
@SupportedSourceVersion(value = SourceVersion.RELEASE_8)
public class InterfaceProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Messager messager = processingEnv.getMessager();
messager.printMessage(Diagnostic.Kind.NOTE, "进入到InterfaceProcessor中了~~~");
// 将带有InterfaceProcessor的类给找出来
Set<? extends Element> clazz = roundEnv.getElementsAnnotatedWith(InterfaceAnnotation.class);
clazz.forEach(item -> {
// 生成一个 I + 类名的接口类
String className = item.getSimpleName().toString();
className = "I" + className.substring(0, 1) + className.substring(1);
TypeSpec typeSpec = TypeSpec.interfaceBuilder(className).addModifiers(Modifier.PUBLIC).build();
try {
// 生成java文件
JavaFile.builder("com.example.processor", typeSpec).build().writeTo(new File("./src/main/java/"));
} catch (IOException e) {
e.printStackTrace();
}
});
return true;
}
}
1. @ SupportedAnnotationTypes:このプロセッサクラスが有効になる注釈を示します
2. @ SupportedSourceVersion:サポートされるJavaバージョンを示します
3.annotations:@SupportedAnnotationTypesに対応する注釈です
4.roundEnv:現在および以前のラウンドを保存します処理環境情報
5. TypeSpecは少しわかりにくいかもしれませんが、javaPoetのクラスです。javaPoetは、javaファイルを生成するためにjavaが使用するサードパーティのプラグインであり、非常に便利なので、このクラスを使用しますjavaファイルを生成するには、中に
実際に、Javaファイルはまた、Javaが付属していたPrintWriterおよび他の入力および出力ストリームを使用して生成することができます。ファイルを生成する多くの方法があります。へのリンクjavaPoetを。javaPoetの利用ガイド。
6メサジェは、出力情報を印刷するために使用され、システム.out.printlnも実際に可能です
。7。プロセスがtrueを返した場合、後続のアノテーションプロセッサはこのアノテーションを再度処理しません。falseの場合、次の処理ラウンドで、他のアノテーションプロセッサも変更されたアノテーションを処理します。
書き込んだ後、ここでMETA-INF / services / javax.annotation.processing.Processorのプロセッサを指定し、com.example.processor.InterfaceProcessorを書き込む必要があります。これが何かわからない場合は、他のブログ(Strength XDのプロモート)SPIとは何ですか?
Mavenで注釈プロセッサとプラグイン設定をコンパイルしています:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<!-- 不加这一句编译会报找不到processor的异常-->
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
このときのディレクトリ構造は次のとおりです。
.
├── HELP.md
├── pom.xml
├── processor.iml
└── src
└── main
├── java
│ └── com
│ └── example
│ └── processor
│ ├── InterfaceAnnotation.java
│ └── InterfaceProcessor.java
└── resources
└── META-INF
└── services
└── javax.annotation.processing.Processor
次に、mvnクリーンインストール。
ステップ3:注釈を使用する
使用する前に、アノテーションプロセッサがコンパイルされている場合は、アノテーションプロセッサのjarパッケージを導入します。
テストクラスに@InterfaceAnnotationを追加します。
@InterfaceAnnotation
public class TestProcessor {
}
mavenは、コンパイル中に使用される注釈プロセッサを指定します。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<annotationProcessors>
<annotationProcessor>
com.example.processor.InterfaceProcessor
</annotationProcessor>
</annotationProcessors>
</configuration>
</plugin>
この時のディレクトリ構造は
.
├── HELP.md
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── test
│ │ └── TestProcessor.java
│ └── resources
└── test.iml
次にmvn compile、javaファイルが生成され、ディレクトリ構造は次のようになります。
.
├── HELP.md
├── pom.xml
├── src
│ └── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ ├── processor
│ │ │ └── ITestProcessor.java // 这里就是生成的java文件
│ │ └── test
│ │ └── TestProcessor.java
│ └── resources
├── target
│ ├── classes
│ │ └── com
│ │ └── example
│ │ └── test
│ │ └── TestProcessor.class
│ ├── generated-sources
│ │ └── annotations
│ └── maven-status
│ └── maven-compiler-plugin
│ └── compile
│ └── default-compile
│ ├── createdFiles.lst
│ └── inputFiles.lst
└── test.iml
生成されたJavaファイルを確認すれば完了です〜
総括する:
1.Javaアノテーションプロセッサは多くの場所で使用できます。1つのアノテーションのみを使用すると、ロンボク、Androidフラグメント生成などの実用的なアプリケーションで多くのコードを節約でき、効率を向上できます
。2。この記事では、非常に単純な例のみを示します。注釈プロセッサのAPIは使用されていません。興味のある読者は自分でそれを調べることができ、抽象構文ツリーに関連するAPIがあります。3。
注釈プロセッサは、特定の機能を完了するための新しいクラスを生成するために使用できますが、直接行うことはできません現在のクラスを変更します。
参考資料:
1. https://docs.oracle.com/javase/8/docs/api/javax/annotation/processing/Processor.html
2. https://jcp.org/aboutJava/communityprocess/final/jsr269/index.html
3. https://github.com/square/javapoet
4. https://www.cnblogs.com/throwable/p/9139908.html
5. http://notatube.blogspot.com/2010/11/project- lombok-trick-explained.html(介绍处理プロセッサー程)
6. https://www.baeldung.com/java-annotation-processing-builder
7. http://hannesdorfmann.com/annotation-processing/annotationprocessing101