Annotation實戰【自定義AbstractProcessor】

DerDAD 10年前發布 | 12K 次閱讀 Java開發 Java annotation

前言

在使用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了。
Annotation實戰【自定義AbstractProcessor】

同時我們可以看一下生成的jar里面都有什么東西:
Annotation實戰【自定義AbstractProcessor】

測試

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

現在編譯測試項目,在輸出console了面觀察日志
Annotation實戰【自定義AbstractProcessor】

參考

  1. http://en.wikipedia.org/wiki/Java_annotation
  2. http://docs.oracle.com/javase/tutorial/java/annotations/
  3. http://programmaticallyspeaking.com/playing-with-java-annotation-processing.html
  4. https://github.com/provegard/aptdemo

via: http://www.cnblogs.com/avenwu/p/4173899.html 

 本文由用戶 DerDAD 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!