- 前言
- 注解處理器
- 自定義處理器
前言
- 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的異常