Annotation Processor(注解處理器)詳解

  • 前言
  • 注解處理器
  • 自定義處理器

前言

  • Java中的注解(Annotation)如果要被識別匆背,離不開注解處理器趁俊。所以有必要來了解一下脚作。

注解處理器

注解處理器(Annotation Processor)是javac的一個工具警没,不管是運行時注解還是編譯時注解匈辱,都會通過處理器在編譯時進行掃描和處理注解。
Java中有默認(rèn)的注解處理器杀迹,使用者也可以自定義注解處理器梅誓,注冊后使用注解處理器處理注解,最終達(dá)到注解本身起到的效果佛南。

注解處理器將標(biāo)記了注解的類梗掰,變量等作為輸入內(nèi)容,經(jīng)過注解處理器處理嗅回,生成想要生成的java代碼及穗。所以處理器可以理解為就是一個生成代碼的工具,只是是通過注解的規(guī)則生成绵载。生成后的代碼埂陆,可以看作是同一般代碼,最終被編譯娃豹。

自定義處理器

創(chuàng)建工程
  • 自定義處理器需要創(chuàng)建java 庫java- Library(自行創(chuàng)建)
添加依賴
  • implementation 'com.google.auto.service:auto-service:1.0-rc3'
  • implementation 'com.google.auto:auto-common:0.8'
創(chuàng)建自定義Processor類 如創(chuàng)建MyProcessor
  • MyProcessor繼承 AbstractProcessor 添加@AutoService(Processor.class)注解
    如:
@AutoService(Processor.class)
public class PermissionProcessor extends AbstractProcessor {

    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);
    }

    @Override
    public Set<String> getSupportedAnnotationTypes() {
        return super.getSupportedAnnotationTypes();
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return super.getSupportedSourceVersion();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        return false;
    }
  • init(ProcessingEnvironment processingEnvironment)
init()方法焚虱,它會被注解處理工具調(diào)用,并輸入ProcessingEnviroment參數(shù)懂版。
ProcessingEnviroment提供很多有用的工具類Elements, Types和Filer鹃栽。
  • getSupportedAnnotationTypes()
這里你必須指定,這個注解處理器是注冊給哪個注解的躯畴。
注意民鼓,它的返回值是一個字符串的集合,包含本處理器想要處理的注解類型的合法全稱蓬抄。換句話說丰嘉,你在這里定義你的注解處理器注冊到哪些注解上。
  • getSupportedSourceVersion()
用來指定你使用的Java版本嚷缭。通常這里返回SourceVersion.latestSupported()饮亏。
如果你有足夠的理由只支持Java 6的話,你也可以返回SourceVersion.RELEASE_6
建議使用前者
  • process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment)
這相當(dāng)于每個處理器的主函數(shù)main()阅爽。掃描路幸、評估和處理注解的代碼,以及生成Java文件优床。
輸入?yún)?shù)RoundEnviroment劝赔,可以讓你查詢出包含特定注解的被注解元素。后面我們將看到詳細(xì)的內(nèi)容胆敞。
  • 注:在Java 7中着帽,你也可以使用注解來代替getSupportedAnnotationTypes()和getSupportedSourceVersion(),像這樣:
    @SupportedAnnotationTypes(“com.starcor.annotation.RouterAnnotation”)移层,其中括號內(nèi)內(nèi)容表示要處理的注解名稱仍翰,要寫全名。
創(chuàng)建javax.annotation.processing.Processor 注冊注解處理器
在使用注解處理器需要先聲明观话,步驟:
1予借、需要在 processors 庫的 main 目錄下新建 resources 資源文件夾;
2频蛔、在 resources文件夾下建立 META-INF/services 目錄文件夾
3灵迫、創(chuàng)建javax.annotation.processing.Processor文件
4、文件內(nèi)容添加:com.xx.java.processor.MyProcessor 自己創(chuàng)建注解處理器的路徑

ProcessingEnvironment 包含了注解處理器相關(guān)的工具類和編譯器配置的參數(shù)

public interface ProcessingEnvironment {
    Map<String, String> getOptions(); // 編譯期間晦溪,app給注解處理器傳的值

    Messager getMessager(); // 在注解處理器處理注解生成新的源代碼過程中瀑粥,我們可用Messager來將一些錯誤信息打印到控制臺上

    Filer getFiler(); // 我們可以通過這個類來創(chuàng)建新的文件。

    /**
    * 它其實是一個工具類三圆,用來處理所有的Element 元素狞换,
    * 而我們可以把生成代碼的類中所有的元素都可以成為Element 元素,
    * 如包就是PackageElement, 
    * 類/接口為TypeElement, 
    * 變量為VariableElement, 
    * 方法為ExecutableElement
    */
    Elements getElementUtils();

    /**
    * 它其實也是一個工具類舟肉,只是用來處理TypeMirror. 也就是一個類的父類修噪。
    * TypeMirror superClassType = currentClass.getSuperclass();
    */
    Types getTypeUtils(); 

    SourceVersion getSourceVersion();

    Locale getLocale();
}

RoundEnvironment 指在每一輪的掃描和處理源代碼中獲取被注解的Element

  • 獲取被注解的Element
Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(GetPermissions.class);
  • 遍歷Element 獲取相應(yīng)添加注解的信息
mElementUtils.getPackageOf(element); // 獲取包名, 通過工具類
 TypeElement classElement = (TypeElement) element.getEnclosingElement(); // 獲取類
classElement.getSimpleName().toString(); // 獲取類名
element.getAnnotation(注解類.class); // 獲取注解的實體類對象路媚,可獲取里面相應(yīng)的值
element.getModifiers() // 獲取修飾符
// 強轉(zhuǎn)方法的Element
ExecutableElement methodElement = (ExecutableElement) element;
// 獲取方法名
String methodName = methodElement.getSimpleName().toString();
executableElement.getParameters(); // 獲取注解形參
executableElement.getReturnType(); // 獲取返回值類型
enclosingElement.getTypeParameters(); // 獲取返回值
executableElement.getThrownTypes(); // 獲取方法throw的異常
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末黄琼,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子整慎,更是在濱河造成了極大的恐慌适荣,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件院领,死亡現(xiàn)場離奇詭異弛矛,居然都是意外死亡,警方通過查閱死者的電腦和手機比然,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門丈氓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人强法,你說我怎么就攤上這事万俗。” “怎么了饮怯?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵闰歪,是天一觀的道長。 經(jīng)常有香客問我蓖墅,道長库倘,這世上最難降的妖魔是什么临扮? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮教翩,結(jié)果婚禮上杆勇,老公的妹妹穿的比我還像新娘。我一直安慰自己饱亿,他們只是感情好蚜退,可當(dāng)我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彪笼,像睡著了一般钻注。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上配猫,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天幅恋,我揣著相機與錄音,去河邊找鬼章姓。 笑死佳遣,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的凡伊。 我是一名探鬼主播零渐,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼系忙!你這毒婦竟也來了诵盼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤银还,失蹤者是張志新(化名)和其女友劉穎风宁,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛹疯,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡戒财,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捺弦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饮寞。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖列吼,靈堂內(nèi)的尸體忽然破棺而出幽崩,到底是詐尸還是另有隱情,我是刑警寧澤寞钥,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布慌申,位于F島的核電站,受9級特大地震影響理郑,放射性物質(zhì)發(fā)生泄漏蹄溉。R本人自食惡果不足惜咨油,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望类缤。 院中可真熱鬧臼勉,春花似錦邻吭、人聲如沸餐弱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽膏蚓。三九已至,卻和暖如春畸写,著一層夾襖步出監(jiān)牢的瞬間驮瞧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工枯芬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留论笔,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓千所,卻偏偏與公主長得像狂魔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淫痰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容