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);