注解是一種能被添加到java代碼中的元數據,類、方法、變量、參數和包都可以用注解來修飾。注解對于它所修飾的代碼并沒有直接的影響。
作用
1.生成幫助文檔。這是最常見的,也是 Java 最早提供的注解。常用的有 @see、@param 和 @return 等;
2.跟蹤代碼依賴性,實現替代配置文件功能。作用就是減少配置。現在的框架基本都使用了這種配置來減少配置文件的數量;
3.在編譯時進行格式檢查。如把 @Override 注解放在方法前,如果這個方法并不是重寫了父類方法,則編譯時就能檢查出。
注解的特點
- 注解可以在變量,方法,類之上加載
- 注解可以有屬性也可以沒有屬性 @Override @Test(timeout=1000)
- 注解有作用范圍(源碼,編譯期間,運行期間)
注解的分類
JDK的,自定義的,第三方的(比如框架)
JDK:
元注解:定義其他注解的注解
- @Retention - 標識這個注解怎么保存,是只在代碼中,還是編入class文件中,或者是在運行時可以通過反射訪問。
- @Documented - 標記這些注解是否包含在用戶文檔中。
- @Target - 標記這個注解應該是哪種 Java 成員。
- @Inherited - 標記這個注解是繼承于哪個注解類(默認注解并沒有繼承于任何子類)
系統注解:
- Override - 檢查該方法是否是重載方法。如果發現其父類,或者是引用的接口中并沒有該方法時,會報編譯錯誤。
- @Deprecated - 標記過時方法。如果使用該方法,會報編譯警告。
- @SuppressWarnings - 指示編譯器去忽略注解中聲明的警告。
三方注解:
框架里面定義的注解,如ButterKnife 框架里面bindview等
自定義注解
定義注解三板斧:
定義注解——相當于定義標記
配置注解——把標記打在需要用到的程序代碼中;
解析注解——在編譯期(別忘了AutoService注冊)或運行時檢測到標記,并進行特殊操作
編譯期注解(APT)原理
APT即為Annotation Processing Tool,它是javac的一個工具,中文意思為編譯時注解處理器。APT可以用來在編譯時掃描和處理注解。通過APT可以獲取到注解和被注解對象的相關信息,在拿到這些信息后我們可以根據需求來自動的生成一些代碼,省去了手動編寫。注意,獲取注解及生成代碼都是在代碼編譯時候完成的,相比反射在運行時處理注解大大提高了程序性能。APT的核心是AbstractProcessor類。
當通過javac將.java文件編譯成.class文件時。編譯過程大致可以分為3個過程:
- 解析與填充符號表過程
- 插入式注解處理器的注解處理過程
- 分析與字節碼生成過程
而插入式注解處理器的注解處理過程主要就是對AbstractProcessor這個類的調用。所以,當我們自定義這個類的子類的時候,在編譯器就會執行這個類中的方法
從JDK1.6開始,提供了插入式注解處理器的標準API在編譯期間對注解進行處理
通過注解處理器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的子類已經有了,但是要想在編譯時期被執行,需要向javac注冊我們這個自定義的注解處理器(即將這個庫變成jar包的形式),這樣,在javac編譯時,才會調用到我們這個自定義的注解處理器方法。
手動注冊:
在src/main目錄下創建resources/META-INF/services/javax.annotation.processing.Processor文件。
在javax.annotation.processing.Processor中寫入自定義的Processor的全名,如果有過個Processor的話,每行寫一個。如:com.soulmate.processor.MyProcessor
自動注冊:
使用AutoService注解,AutoService會自動在META-INF文件夾下生成Processor配置信息文件,該文件里就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,
就能通過該jar包META-INF/services/里的配置文件找到具體的實現類名,并裝載實例化,完成模塊的注入。應用依賴如下
compile 'com.google.auto.service:auto-service:1.0-rc2'
APT應用場景
APT技術被廣泛的運用在Java框架中,包括Android項目以及Java后臺項目,除了上面我們提到的ButterKnife之外,像EventBus 、Dagger2以及阿里的ARouter路由框架等都運用到APT技術