在android开发中有不少运用到注解处理器(annotation processing)的框架,如常见的Butterknife,Dagger2,EventBus等,运用这些注解处理器框架大大简化了咱们的代码。这里主要讲解自定义注解处理器的原理。java
在自定义注解时,通常须要掌握如下几个知识点:android
在《深刻理解Java虚拟机》中早期(编译器)优化章节中,当经过javac
将.java
文件编译成.class
文件时。编译过程大体能够分为3个过程:git
而插入式注解处理器的注解处理过程
主要就是对AbstractProcessor这个类的调用。因此,当咱们自定义这个类的子类的时候,在编译器就会执行这个类中的方法。github
对注解(Annotation)的支持时从JDK1.5开始的,但这个时候的注解只在运行期间发挥做用。从JDK1.6开始,提供了插入式注解处理器的标准API在编译期间对注解进行处理。这也就要求咱们依赖的JDK版本应该高于1.6(包括1.6)。bash
在javac源码中,插入式注解处理器的初始化过程是在initProcessAnnotations()方法中完成的,而它的执行过程则是在processAnnotations()方法中完成的,这个方法判断是否有新的注解处理器须要执行,若是有的话,经过com.sun.tools.javac.processing.JavacProcessingEnvironment类的doProcessing()方法生成一个新的JavaCompiler对象对编译的后续步骤进行处理。框架
上面介绍了注解处理器在javac源码中的调用过程,而在具体的经过注解处理器API实现一个编译器插件,须要继承抽象类javax.annotation.processing.AbstractProcessor,重写抽象方法process()
,这个方法在javac编译器在执行注解处理器代码时调用。这个方法有两个参数,第一个参数表示注解处理器全部处理的注解集合,第二个参数roundEnvironment
表示当前这个Round中的语法树节点,每一个语法树节点在这里表示一个Element。这里的Element包括以下元素:包(PACKAGE)、枚举(ENUM)、类(CLASS)、注解(ANNOTATION_TYPE)、接口(INTERFACE)等。优化
由此可知,咱们在android开发中使用的AbstractProcessor
这个类是JDK经过javac编译的时候用来处理注解的。而android sdk
中删除了这个类,因此咱们须要经过建立java library
库来获取这个类。至此,咱们大概理解了AbstractProcessor
这个类执行时机和建立方法。ui
如今自定义AbstractProcessor
的子类已经有了,可是要想在编译时期被执行,须要向javac注册咱们这个自定义的注解处理器(即将这个库变成jar包的形式),这样,在javac编译时,才会调用到咱们这个自定义的注解处理器方法。那么如何设置成jar包了。这就引出下面的auto-service库了。spa
正常状况下,向javac中注册自定义的处理器的步骤以下:插件
com.soulmate.processor.MyProcessor
复制代码
这样,在javac编译时,在处理注解处理器的时候就会执行咱们自定义的注解处理器。
上面是正常的一种人工设置的方法,可是每次这样配置的话一个是写起来很麻烦,还有若是我修改了自定义的AbstractAnnotation子类的类名的话,可能会由于忘了修改而致使错误,而auto-service这个库就是为了解决这个问题。它能够自动完成上面须要添加的步骤,只须要在自定义的注解处理器类上面添加@AutoService(Processor.class)这个注解就能够了。这样也能够避免上面所说的问题。具体使用能够看一下官方文档。
到这里在编译的时候自定义的注解处理器已经能够被执行了,那么javapoet
是干吗的了?其实在自定义注解处理器的process()
方法中,咱们常常须要生成须要的java类,这个能够参考ButterKnife
框架中的ButterKnifeProcessor
类中process()
方法,在这个方法中就是使用javapoet来生成须要的类,生成的类中定义了findViewById()方法。
javapoet是square开源的一个java生成库,官网解释为:
JavaPoet is a Java API for generating `.java` source files
复制代码
javapoet的使用比较简单,官方文档给出了很是详细的讲解。因此这里就不过多的介绍,具体的使用能够看官网的示例。
到这里关于整个自定义注解处理器的流程就介绍完了,这里主要介绍的是编译器的注解处理器。包括整个编译时注解在源码中的调用流程。