Android编译时注解框架的一般套路
一、注解框架的目的
编译时注解框架的目的,一般都是将一些有迹可循的、重复的操作在编译时自动执行,预生成一些代码,以替换人类机械的、耗时的劳作方式,达到在空间和时间维度的效率优化。
二、预先要掌握的知识和工具
- 知识
- Java Annotation
- javax.lang.model.*(Java编程语言建模)
- Java Service Provider Interface 技术(简称Java SPI)
- Annotation Processing Tool 技术(简称APT)
- 工具
- javapoet
- auto-service
三、编写注解
注解框架,那么先得有注解,自定义的注解。
形如:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface Router {
String address();
}
四、解析注解
解析注解,首先需要了解Java SPI 和 Android APT这2个技术。
APT技术
,JDK 1.6中,提供了一组插入式注解处理器的标准API(Processor)
,其可以在编译期间对注解进行处理。
SPI技术
,是Java的一个技术,概括的讲,用于反射加载某个服务(接口)的所有实现。
而Auto-Service是SPI技术的一个自动化Library。
结合起来,就是通过SPI技术来加载APT技术中的Processor(注解处理器接口)的具体实现,形如:
ServiceLoader<Display> loader = ServiceLoader.load(Processor.class);
mIterator = loader.iterator();
while (mIterator.hasNext()){
mIterator.next().process();
}
总结解析注解的流程就是:
在编译的时候,JVM通过Java SPI技术加载Processor服务的所有实现,这些实现就是我们自定义的注解处理器。
注解处理器处理注解的流程,这里引用这篇博客的一段话和图,`详见地址
编译器在构建了抽象语法树之后,如果注解处理器在处理注解期间对语法树进行了修改,编译器将回到解析与填充符号表的过程重新处理,直到所有插入式注解处理器都没有再对语法树进行修改为止,每一次循环称为一个Round,如下图中的环。
如何才是注解处理器对语法树进行了修改?就是注解处理器的process方法返回true
,譬如Auto-Service的注解处理器AutoServiceProcessor
。
在Android中,为了使自定义的[注解处理器模块]
的内容只在编译期间作为依赖,不需要打包到apk中作为项目的最终内容,提供了内置的插件 annotationProcessor
五、达成目的
知道一个大概的流程之后,我们需要在自定义的注解处理器中,真正开始实现process
方法,达到譬如类似控制反转的目的。
重点是Processor服务的process方法,基于编写框架的目的,其方法具体生成什么样的文件资源也不一样,但是原理和工具是一致的,还需要了解javax.lang.model
包中的一些类成员和层次结构。
了解了javax.lang.model
,剩下我们主要需要去做的,就是将注解处理器供我们使用的Elements做梳理,然后提供给工具javapoet
生成需要的文件资源。
javapoet
这个library可以识别javax.lang.model
包中的类成员和层次结构,然后利用这些像作诗一样生成java文件资源。
最后
其实编写一个注解框架最难的地方,不是上面这些概念,而是需要透彻理解Java语言编程模型,也就是javax.lang.model包中的类成员以及层次结构,只有这样才能游刃有余!
也准备专门写一篇笔记讲下Java语言的编程模型沉淀一番…(┬_┬)