AbstractProcessor 註解處理器
javac的一個工具,用來在編譯時掃描和編譯和處理註解(Annotation)的。只能生成新文件。
-
ProcessingEnvironment
提供 Element,Filer,Messager等工具,Filer在生成java文件使用,Messager可以打印日誌,調試時使用的最多。 (Messager日誌在Android studio - Build - Toggle View面板查看)
-
getSupportedAnnotationTypes() 指定當前處理器可以處理的註解
-
getSupportedSourceVersion() 指定java版本
-
process () 正真處理註解邏輯的地方
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (set.isEmpty()) {
mMessager.printMessage(Diagnostic.Kind.WARNING, DialogAnnotation.class.getSimpleName() + " is not used");
return false;
}
//1、獲取註解處理器標記的所有元素
Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(DialogAnnotation.class);
//2、遍歷元素,拿到註解值
for (Element element : elementsAnnotatedWith) {
//3、判斷元素類型是否是欲處理的類,element.asType()可以拿到具體類型
if (!element.getKind().isClass()) {
continue;
}
String clazzName = element.toString();
//4、獲取元素上所有註解
List<? extends AnnotationMirror> annotationMirrors = element.getAnnotationMirrors();
for (AnnotationMirror mirror : annotationMirrors) {
//獲取元素值
Set<? extends Map.Entry<? extends ExecutableElement, ? extends AnnotationValue>> entrySet = mirror.getElementValues().entrySet();
//5、遍歷註解上的每個鍵值對
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : entrySet) {
//鍵
Name key = entry.getKey().getSimpleName();
//值
String value = entry.getValue().toString();
...處理過程...
}
//打印日誌
mMessager.printMessage(Diagnostic.Kind.NOTE, "日誌信息");
}
}
//6、根據處理過程中的到的數據生成java文件
createJavaFile(xxx);
return true;
}
JavaPoet
一個用來生成java文件的第三方庫
類
MethodSpec
代表一個構造函數或方法聲明
TypeSpec
代表一個類,接口,或者枚舉聲明
FieldSpec
代表一個成員變量,一個字段聲明
JavaFile
包含一個頂級類的Java文件
ParameterSpec
用來創建參數
AnnotationSpec
用來創建註解
ClassName
表示一個類,如Activity類爲:
ClassName activityClassName = ClassName.get("android.app", "Activity");
TypeName
表示類型
佔位符
$L 字面量 用於拼接字符串,不會添加""
$S 字符串 會在值前後加""
$T 類、接口
$N 變量
github例子
package com.example.helloworld;
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
// And this is the (exciting) code to generate it with JavaPoet:
MethodSpec main = MethodSpec.methodBuilder("main") //指定方法名
.addModifiers(Modifier.PUBLIC, Modifier.STATIC) //添加訪問級別修飾符
.returns(void.class) //添加返回值類型
.addParameter(String[].class, "args") //添加參數,可以調用多次
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") //具體代碼
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") //定義一個類,名爲HelloWorld
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main) //添加方法,可以調用多次
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build(); //指定包名,生成java文件
javaFile.writeTo(System.out);