一、项目结构
项目结构需要有注解工程(属于Java工程)、注解处理工程(属于Java工程),如下图所示:
二、APT技术简介
APT(Annotation Processing Tool) 是一种处理注释的工具,它对源代码文件进行检测找出其中的Annotation,根据注解自动生成代码,如果想要自定义的注解处理器能够正常运行,必须要通过APT工具来进行处理。(总而言之,就是通过注解自动生成Java代码)
三、如何确保注解处理程序编译OK
如下图所示,ARouterProcessor.java 在META-INF 中存在对应的注册
四、处理程序代码编写
package com.lgj.compiler;
import com.google.auto.service.AutoService;
import com.lgj.arouter_annotations.ARouter;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
/*
* 所有的注解写在一起,是为了框架的独立性
* 注解处理器,通过注解生成Java代码 apt技术
* 是一个背后的服务,
* */
// 对ARouter 注解的处理
@AutoService(Processor.class) // 启用服务
@SupportedAnnotationTypes({"com.lgj.arouter_annotations.ARouter"})// 需要对那个注解进行处理
@SupportedSourceVersion(SourceVersion.RELEASE_7)// 环境的版本
// 接收 安卓工程传递过来的参数
@SupportedOptions("student")
public class ARouterProcessor extends AbstractProcessor {
// 操作Element的工具类(类,函数,属性,其实都是Element)
private Elements elementTool;
// type(类信息)的工具类,包含用于操作TypeMirror的工具方法
private Types typeTool;
// Message用来打印 日志相关信息
private Messager messager;
// 文件生成器, 类 资源 等,就是最终要生成的文件 是需要Filer来完成的
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
elementTool = processingEnvironment.getElementUtils();
messager = processingEnvironment.getMessager();
filer = processingEnvironment.getFiler();
// 把Android端,传递过来的参数,打印出来
String value = processingEnvironment.getOptions().get("student");
// 如果我想在注解处理器里面抛出异常 可以使用Diagnostic.Kind.ERROR
// 正常的打印日志,采用note级别的就行
messager.printMessage(Diagnostic.Kind.NOTE,">>>>>>>>>>>>>>>>>>>>>>>>>>> lgj :" + value);
}
// 在编译的时候干活,如果APP壳中没有使用任何的注解,那么这个函数不会执行
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
messager.printMessage(Diagnostic.Kind.NOTE,">>>>>>>>>>>>>>>>>>>>>>>>>>> lgj run ...");
/**
模块一
package com.example.helloworld;
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
*/
// 通过JavaPote 生成上面的类
// 获取被 ARouter 注解的 "类节点信息"
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
for (Element element : elements) {
// Java 万物接皆对象
// 1.方法
MethodSpec mainMethod = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class,"args")
// 增加main方法里面的内容
// $T 代表类,相当于占位符,$S 代表字符串
.addStatement("$T.out.println($S)",System.class,"hellp JavaPoet")
.build();
// 2.类
TypeSpec testClass = TypeSpec.classBuilder("LgjTest")
.addMethod(mainMethod)
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.build();
// 3.包
JavaFile packagef = JavaFile.builder("com.xiangxue.test", testClass).build();
// 生成文件
try {
packagef.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
messager.printMessage(Diagnostic.Kind.NOTE, "生成Test文件时失败,异常:" + e.getMessage());
}
}
return false; // false不干活了 true干完了
}
}