Android自定義註解處理器

前言

在android開發中有不少運用到註解處理器(annotation processing)的框架,如常見的Butterknife,Dagger2,EventBus等,運用這些註解處理器框架大大簡化了咱們的代碼。這裏主要講解自定義註解處理器的原理。java

知識點

在自定義註解時,通常須要掌握如下幾個知識點:android

  • AbstractProcessor相關知識
  • auto-service相關知識
  • javapoet相關知識

AbstractProcessor簡介

在《深刻理解Java虛擬機》中早期(編譯器)優化章節中,當經過javac.java文件編譯成.class文件時。編譯過程大體能夠分爲3個過程:git

  • 解析與填充符號表過程
  • 插入式註解處理器的註解處理過程
  • 分析與字節碼生成過程

插入式註解處理器的註解處理過程主要就是對AbstractProcessor這個類的調用。因此,當咱們自定義這個類的子類的時候,在編譯器就會執行這個類中的方法。github

對註解(Annotation)的支持時從JDK1.5開始的,但這個時候的註解只在運行期間發揮做用。從JDK1.6開始,提供了插入式註解處理器的標準API在編譯期間對註解進行處理。這也就要求咱們依賴的JDK版本應該高於1.6(包括1.6)。bash

在javac源碼中,插入式註解處理器的初始化過程是在initProcessAnnotations()方法中完成的,而它的執行過程則是在processAnnotations()方法中完成的,這個方法判斷是否有新的註解處理器須要執行,若是有的話,經過com.sun.tools.javac.processing.JavacProcessingEnvironment類的doProcessing()方法生成一個新的JavaCompiler對象對編譯的後續步驟進行處理。框架

上面介紹了註解處理器在javac源碼中的調用過程,而在具體的經過註解處理器API實現一個編譯器插件,須要繼承抽象類javax.annotation.processing.AbstractProcessor,重寫抽象方法process(),這個方法在javac編譯器在執行註解處理器代碼時調用。這個方法有兩個參數,第一個參數表示註解處理器全部處理的註解集合,第二個參數roundEnvironment表示當前這個Round中的語法樹節點,每一個語法樹節點在這裏表示一個Element。這裏的Element包括以下元素:包(PACKAGE)、枚舉(ENUM)、類(CLASS)、註解(ANNOTATION_TYPE)、接口(INTERFACE)等。優化

由此可知,咱們在android開發中使用的AbstractProcessor這個類是JDK經過javac編譯的時候用來處理註解的。而android sdk中刪除了這個類,因此咱們須要經過建立java library庫來獲取這個類。至此,咱們大概理解了AbstractProcessor這個類執行時機和建立方法。ui

如今自定義AbstractProcessor的子類已經有了,可是要想在編譯時期被執行,須要向javac註冊咱們這個自定義的註解處理器(即將這個庫變成jar包的形式),這樣,在javac編譯時,纔會調用到咱們這個自定義的註解處理器方法。那麼如何設置成jar包了。這就引出下面的auto-service庫了。spa

auto-service簡介

正常狀況下,向javac中註冊自定義的處理器的步驟以下:插件

  1. 在src/main目錄下建立resources/META-INF/services/javax.annotation.processing.Processor文件。
  2. 在javax.annotation.processing.Processor中寫入自定義的Processor的全名,若是有過個Processor的話,每行寫一個。以下:
com.soulmate.processor.MyProcessor
複製代碼

這樣,在javac編譯時,在處理註解處理器的時候就會執行咱們自定義的註解處理器。

上面是正常的一種人工設置的方法,可是每次這樣配置的話一個是寫起來很麻煩,還有若是我修改了自定義的AbstractAnnotation子類的類名的話,可能會由於忘了修改而致使錯誤,而auto-service這個庫就是爲了解決這個問題。它能夠自動完成上面須要添加的步驟,只須要在自定義的註解處理器類上面添加@AutoService(Processor.class)這個註解就能夠了。這樣也能夠避免上面所說的問題。具體使用能夠看一下官方文檔。

到這裏在編譯的時候自定義的註解處理器已經能夠被執行了,那麼javapoet是幹嗎的了?其實在自定義註解處理器的process()方法中,咱們常常須要生成須要的java類,這個能夠參考ButterKnife框架中的ButterKnifeProcessor類中process()方法,在這個方法中就是使用javapoet來生成須要的類,生成的類中定義了findViewById()方法。

javapoet簡介

javapoet是square開源的一個java生成庫,官網解釋爲:

JavaPoet is a Java API for generating `.java` source files
複製代碼

javapoet的使用比較簡單,官方文檔給出了很是詳細的講解。因此這裏就不過多的介紹,具體的使用能夠看官網的示例

總結

到這裏關於整個自定義註解處理器的流程就介紹完了,這裏主要介紹的是編譯器的註解處理器。包括整個編譯時註解在源碼中的調用流程。

相關文章
相關標籤/搜索