在android開發中有不少運用到註解處理器(annotation processing)的框架,如常見的Butterknife,Dagger2,EventBus等,運用這些註解處理器框架大大簡化了咱們的代碼。這裏主要講解自定義註解處理器的原理。java
在自定義註解時,通常須要掌握如下幾個知識點:android
在《深刻理解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
正常狀況下,向javac中註冊自定義的處理器的步驟以下:插件
com.soulmate.processor.MyProcessor
複製代碼
這樣,在javac編譯時,在處理註解處理器的時候就會執行咱們自定義的註解處理器。
上面是正常的一種人工設置的方法,可是每次這樣配置的話一個是寫起來很麻煩,還有若是我修改了自定義的AbstractAnnotation子類的類名的話,可能會由於忘了修改而致使錯誤,而auto-service這個庫就是爲了解決這個問題。它能夠自動完成上面須要添加的步驟,只須要在自定義的註解處理器類上面添加@AutoService(Processor.class)這個註解就能夠了。這樣也能夠避免上面所說的問題。具體使用能夠看一下官方文檔。
到這裏在編譯的時候自定義的註解處理器已經能夠被執行了,那麼javapoet
是幹嗎的了?其實在自定義註解處理器的process()
方法中,咱們常常須要生成須要的java類,這個能夠參考ButterKnife
框架中的ButterKnifeProcessor
類中process()
方法,在這個方法中就是使用javapoet來生成須要的類,生成的類中定義了findViewById()方法。
javapoet是square開源的一個java生成庫,官網解釋爲:
JavaPoet is a Java API for generating `.java` source files
複製代碼
javapoet的使用比較簡單,官方文檔給出了很是詳細的講解。因此這裏就不過多的介紹,具體的使用能夠看官網的示例。
到這裏關於整個自定義註解處理器的流程就介紹完了,這裏主要介紹的是編譯器的註解處理器。包括整個編譯時註解在源碼中的調用流程。