作用:
注解处理器就是将注解生成对应的java类,生成java类可以使用javaPoet。
如何自定义注解处理器呢?有以下步骤:
1、我们创建一个module,名字为testProcessor,注意它是一个java library;如果是一个java library,在testProcessorx下的build.gradle中第一行是apply plugin: 'java-library',但是这个插件只有在gradle 4才支持,修改方式:file--->project structure--->Project---->gradle version 将版本改成4.1
2、创建一个注解类,这个类必须继承自AbstractProcessor,如下所示:
public class TestProcessor extends AbstractProcessor
其实注解类和我们的Activity一样也需要注册,但是我们可以使用google自带的工具auto-service,testProcessor中的build.gradle代码如下:
apply plugin: 'java-library' //引入的插件,需要将gradle版本修改到4以上
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.auto.service:auto-service:1.0-rc2' //引入auto-service实现注解自动注册
implementation 'com.squareup:javapoet:1.7.0' //使用开源框架javapoet生成Java类
}
sourceCompatibility = "1.7" //指定java兼容版本
targetCompatibility = "1.7"
同时我们需要注解类上添加一些注解,代码如下:
@AutoService(Processor.class) //使用此注解自动注册,
//当前注解处理器能够处理的注解 代替 getSupportedAnnotationTypes函数
@SupportedAnnotationTypes({"com.example.administrator.apt.Route"})//定义注解处理器需要处理注解的类型
//java版本 代替 getSupportedAnnotationTypes 函数
@SupportedSourceVersion(SourceVersion.RELEASE_7) //指定jdk的版本
public class TestProcessor extends AbstractProcessor {
这就是注解器注册的位置,然后文件中的内容就是我们注解器的全类名,如com.example.testprocessor.TestProcessor
然后在app中的build.gradle中引用此注解:
annotationProcessor project(':testProcessor')
3、重写注解器的init方法和process方法,代码如下:
/**
* Created by Administrator on 2018/3/21.
*/
@AutoService(Processor.class)
//当前注解处理器能够处理的注解 代替 getSupportedAnnotationTypes函数
@SupportedAnnotationTypes({"com.example.administrator.apt.Route"})
//java版本 代替 getSupportedAnnotationTypes 函数
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class TestProcessor extends AbstractProcessor {
private Messager messager;
Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
filer = processingEnvironment.getFiler();
messager = processingEnvironment.getMessager();//获取信息打印工具
messager.printMessage(Diagnostic.Kind.NOTE, "TestProcessor=============init");//打印信息,在Gradle Console可以看到打印信息,如果第一个参数写成Kind.ERROR将会信息中断
}
@Override
public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
messager.printMessage(Diagnostic.Kind.NOTE, "TestProcessor=============process");
for (TypeElement typeElement : set) {//set集合都是注解节点,但是我们要拿到的是被注解的节点
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")//创建类
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();//创建文件
try {
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
}
以上process方法中的for中的作用就是生成java类,java文件,此文件存放app--build---generated---source--apt如下所示;
4、如果需要传递参数,我们可以在app的build.gradle中的defaultConfig中配置一下代码:
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
同时在TestlProcessor之上添加一个注解
/**
* 处理器接收的参数 替代 {@link AbstractProcessor#getSupportedOptions()} 函数
*/
@SupportedOptions("moduleName")