Annotation實戰【自定義AbstractProcessor】
前言
在使用Java的過程中,每個開發人員都接觸過@Override, @Deprecated等等各式各樣的注解,這些東西是java最基礎的一些原生定義好的annotation。本文通過一個實例演示如果自定義自己的annotation,使得在編譯源碼代碼階段進行額外操作。案例源碼
預熱
簡單說一下annotation的基本知識,從java的官方技術文檔可以直接找到annotation的技術點。
Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
Annotations是一種元數據,其作用在于提供程序本身以外的一些數據信息,也就是說Annotation他不會屬于程序代碼本身,不參與邏輯運算,故而不會對原程序代碼的操作產生直接的影響。
一般來說Annotation有如下三種使用情形:
- Information for the compiler — Annotations can be used by the compiler to detect errors or suppress * warnings.
- Compile-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.
- Runtime processing — Some annotations are available to be examined at runtime.
- 為編譯器提供輔助信息 — Annotations可以為編譯器提供而外信息,以便于檢測錯誤,抑制警告等.
- 編譯源代碼時進行而外操作 — 軟件工具可以通過處理Annotation信息來生成原代碼,xml文件等等.
- 運行時處理 — 有一些annotation甚至可以在程序運行時被檢測,使用.
具體annotation的詳細知識點可以參考技術文檔,本文案例針對的是編譯源代碼時進行而外操作。
目標
用過頂頂大名的Dagger,Butterknife等依賴注入的童鞋可能知道,他們就通過運行時annotation預處理技術實現動態的生成代碼。現在我們先做一個簡單的案例:
通過定義一個annotation,在編譯代碼的時候,凡是用該annotation聲明過的類,方法,我們都要在控制臺輸出他們的信息
下文涉及的編碼等工作是基于IntelliJ Idea和Android Studio,讀者也可以根據自己的實際情況選用其他諸如Eclipse的工具。
開工
首先用IntelliJ新建一個java標準工程,同時勾選maven支持,我們需要新建一個自己的AbstractProcessor類, 其中process為主要方法,在里面處理接收到的所有被PrintMe修飾過的元素,這里是直接輸出器信息。
@SupportedAnnotationTypes({"com.avenwu.annotation.PrintMe"})
public class MyProcessor extends AbstractProcessor {
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
Messager messager = processingEnv.getMessager();
for (TypeElement te : annotations) {
for (Element e : env.getElementsAnnotatedWith(te)) {
messager.printMessage(Diagnostic.Kind.NOTE, "Printing: " + e.toString());
}
}
return true;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}</code></pre>
現在新建PrintMe,簡單起見現在可以什么不寫,僅需標注其使用策略為RetentionPolicy.SOURCE
@Retention(RetentionPolicy.SOURCE)
public @interface PrintMe {
}
現在我們需要生成jar文件,修改pom.xml,默認生成的pom.xml需要再添加jar,和maven-compiler-plugin,修改完畢后應該如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0 ;
<modelVersion>4.0.0</modelVersion>
<groupId>groupId</groupId>
<artifactId>AnnotationProcessorTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<!-- Disable annotation processing for ourselves. -->
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
</project></code></pre>
為了我們的AbstractProcessor內被使用,需要在META-INF中顯示標識,在resources資源文件夾下新建META-INF/services/javax.annotation.processing.Processor
com.avenwu.annotation.MyProcessor
至此可以build生成jar了。

同時我們可以看一下生成的jar里面都有什么東西:

測試
現在我們需要測試一下生成的jar包是不是如預期能輸出信息。將AnnotationProcessorTest.jar拷貝置一個測試項目的libs,然后在任意選擇幾個位置用PrintMe修飾:


現在編譯測試項目,在輸出console了面觀察日志

參考
- http://en.wikipedia.org/wiki/Java_annotation
- http://docs.oracle.com/javase/tutorial/java/annotations/
- http://programmaticallyspeaking.com/playing-with-java-annotation-processing.html
- https://github.com/provegard/aptdemo
via: http://www.cnblogs.com/avenwu/p/4173899.html