带你读《2022技术人的百宝黑皮书》——一个搞定责任链的注解(4)https://developer.aliyun.com/article/1339674?groupCode=taobaotech
生成原理
通过SPI的方式注册编译时注解@AutoPipelineProcessor,在编译过程中通过javapoet框架生成业务pipeline源 代码。
注册编译时注解
编写注解类:AutoPipelineProcessor
继承JDK的 AbstractProcessor , 实现process 方法 在resources目录下新建文件夹:META-INF/services
在META-INF/services里面新增spi文件:javax.annotation.processing.Processor,文件写入需要继承 AbstractProcessor的全类名
相 关 类 介 绍 : Processor:提供注解处理,它遵循SPI规约进行拓展AbstractProcessor:注解处理器主要拓展处理类
生成源代码
JDK术语介绍:
ProcessingEnvironment
注解处理工具的集合
Element
是一个接口,表示一个程序元素,它可以是包、类、方法或者一个变量
PackageElement
表示一个包程序元素,提供对有关包及其成员的信息的访问。
ExecutableElement
表示某个类或接口的方法、构造方法或初始化程序(静态或实例),包括注释类型元素。
TypeElement
表示一个类或接口程序元素,提供对有关类型及其成员的信息的访问。注意,枚举类型是一种类,而注解类型是一种接口。
VariableElement
表示一个字段、enum 常量、方法或构造方法参数、局部变量或异常参数。Filer
文件管理器,主要负责生成源代码、class 或者辅助文件
JavaPoet技术介绍: TypeSpec
用于生成类、接口、枚举的工具类MethodSpec
用于生成构造方法或者普通的方法的工具类
关键代码解读
生成入口:AutoPipelineProcessor#process
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean { val elements = roundEnv.getElementsAnnotatedWith(AutoPipeline::class.java) if (elements.isEmpty()) { return false } for (element in elements) { if (element.kind != ElementKind.INTERFACE) { error(element, "${(element as TypeElement).qualifiedName} is not a interface! Only interface can annotated with @${AutoPipeline::class.simpleName}") return false } if (!element.modifiers.contains(Modifier.PUBLIC)) { error(element, "interface ${(element as TypeElement).qualifiedName} is not public! Only public interface can annotated with @${AutoPipeline::class.simpleName}")
15 |
|
return false |
16 |
|
} |
17 |
|
|
18 |
|
if (element is TypeElement) { |
19 |
|
doProcess(element) |
20 |
|
} |
21 |
|
} |
22 |
|
|
23 |
|
return false |
24 |
} |
通过roundEnv 获取所有被AutoPipeline注释修饰的类,如果没有则直接返回遍历elements,处理每个element (被注解的类必须是public修饰的接口)
生成源码门户:SourceGeneratorFacade#genSourceCode
带你读《2022技术人的百宝黑皮书》——一个搞定责任链的注解(6)https://developer.aliyun.com/article/1339672?groupCode=taobaotech