前言

Java中的注解(Annotation)如果要被识别,离不开注解处理器。所以有必要来了解一下。

注解处理器

注解处理器(Annotation Processor)是javac的一个工具,不管是运行时注解还是编译时注解,都会通过处理器在编译时进行扫描和处理注解。
Java中有默认的注解处理器,使用者也可以自定义注解处理器,注册后使用注解处理器处理注解,最终达到注解本身起到的效果。

注解处理器将标记了注解的类,变量等作为输入内容,经过注解处理器处理,生成想要生成的java代码。所以处理器可以理解为就是一个生成代码的工具,只是是通过注解的规则生成。生成后的代码,可以看作是同一般代码,最终被编译。

自定义处理器

如果java提供的注解处理器不能满足需求,那就可以自定义。自定义的注解处理器要遵循java中标准处理器的接口。

1.创建工程
首先注解处理器需要javax包的支持,Android环境下是访问不到javax包的。
需要创建Java Library包来提供javax环境,另外注解处理器要被打包进jar包里面才能被系统识别,这就是选用ava Library的原因,目前注解注解框架均是如此。
Android studio中,选择创建新的module,选择Java Library**(该lib是注解处理器的lib、另外注解本身的lib也需要单独创建一个annotation的lib,此处就不讲了。)**

2. 继承虚处理器AbstractProcessor
AbstractProcessor在JDk的rt,jar中:

每个处理器都要继承该类,如:

package com.starcor.processor.router;import java.util.Set;import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;public class RouterProcessor  extends AbstractProcessor {@Overridepublic boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {return false;}@Overridepublic synchronized void init(ProcessingEnvironment processingEnvironment) {super.init(processingEnvironment);}@Overridepublic Set<String> getSupportedAnnotationTypes() {return super.getSupportedAnnotationTypes();}@Overridepublic SourceVersion getSupportedSourceVersion() {return super.getSupportedSourceVersion();}
}
  • init(ProcessingEnvironment processingEnvironment):
    每一个注解处理器类都必须有一个空的构造函数。然而,这里有一个特殊的init()方法,它会被注解处理工具调用,并输入ProcessingEnviroment参数。ProcessingEnviroment提供很多有用的工具类Elements, Types和Filer。后面我们将看到详细的内容。
  • process(Set<? extends TypeElement> annotations, RoundEnvironment env):
    这相当于每个处理器的主函数main()。扫描、评估和处理注解的代码,以及生成Java文件。输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素。后面我们将看到详细的内容。
  • getSupportedAnnotationTypes():
  • 这里你必须指定,这个注解处理器是注册给哪个注解的。注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称。换句话说,你在这里定义你的注解处理器注册到哪些注解上。
  • getSupportedSourceVersion():
  • 用来指定你使用的Java版本。通常这里返回SourceVersion.latestSupported()。然而,如果你有足够的理由只支持Java 6的话,你也可以返回SourceVersion.RELEASE_6。我推荐你使用前者。
    在Java 7中,你也可以使用注解来代替getSupportedAnnotationTypes()和getSupportedSourceVersion(),像这样:
    @SupportedAnnotationTypes(“com.starcor.annotation.RouterAnnotation”),其中括号内内容表示要处理的注解名称,要写全名。
package com.starcor.processor.router;import java.util.Set;import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;@SupportedAnnotationTypes("com.starcor.annotation.RouterAnnotation")
public class RouterProcessor  extends AbstractProcessor {@Overridepublic boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {return false;}@Overridepublic synchronized void init(ProcessingEnvironment processingEnvironment) {super.init(processingEnvironment);}@Overridepublic Set<String> getSupportedAnnotationTypes() {return super.getSupportedAnnotationTypes();}@Overridepublic SourceVersion getSupportedSourceVersion() {return super.getSupportedSourceVersion();}
}

3. 注册处理器
以上已经把完成了处理器的工作,但是处理器要被识别 ,还需要被注册。
注册方式一:手动注册
在使用注解处理器需要先声明,步骤:
1、需要在 processors 库的 main 目录下新建 resources 资源文件夹;
2、在 resources文件夹下建立 META-INF/services 目录文件夹

在文件java.lang.Process中增加注册器路径名:
com.starcor.processor.router.RouterProcessor

方式二:自动注册
google提供了一个注册处理器的库AutoService。帮助将要编译的处理器进行编译。
compile ‘com.google.auto.service:auto-service:1.0-rc2’

apply plugin: 'java-library'dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])
}sourceCompatibility = "1.7"
targetCompatibility = "1.7"dependencies {compile 'com.google.auto.service:auto-service:1.0-rc2'
}

然后再processor中使用注解:
@AutoService(Processor.class)
public class RouterProcessor extends AbstractProcessor {

}

此时编译时候就会生成文件目录如下:***(但是我这边验证使用AutoService自动注册存在问题,生成的文件为java.lang.Process,暂不明白什么原因,所以使用的手动注册方式)***

处理器对全局代码的扫描处理流程
注解处理器对工程代码的扫描是多次的,可以注意到AbstractProcessor的process()方法的输入参数有一个是RoundEnvironment,这个代表一次扫描的结果。
4. 使用处理器
再应用工程中,测试注解处理器。
在工程的build.gradle中增加使用的处理器:
implementation project(’:annotation’)
annotationProcessor project(’:Processor’)

dependencies {implementation fileTree(include: ['*.jar'], dir: 'libs')implementation 'com.android.support:appcompat-v7:26.1.0'testImplementation 'junit:junit:4.12'androidTestImplementation 'com.android.support.test:runner:1.0.2'androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'annotationProcessor project(':Processor')implementation project(':annotation')
}

验证是否执行了注解处理器,可以init中增加打印,在gradle console中可以查看到:

    @Overridepublic synchronized void init(ProcessingEnvironment processingEnvironment) {super.init(processingEnvironment);messager = processingEnvironment.getMessager();//获取信息打印工具messager.printMessage(Diagnostic.Kind.NOTE, "TestProcessor=============init");//打印信息,在Gradle Console可以看到打印信息,如果第一个参数写成Kind.ERROR将会信息中断}

打印如下:
整个工程目录如下:

app是使用注解的app模块; Processor是处理注解生成动态代码的模块;annotation是注解定义模块;
生成的文件目录一般为:

总结

以上说明了怎么实现一个自定义的注解处理器,但是注解处理器根本没有做什么事情。编译时注解一般是要生成java的class文件,那么怎么生成呢?我们可以借助javapoet来实现。javapoet是一个生成java源文件的框架。后面来讲一下生成规则。
所以,一般情形,增加一个自定义注解处理器,离不开3个概念:

procesor:注解处理类,另外AutoService和javapoet来完成源代码的生成
AutoService :作用是注解 processor 类,并对其生成 META-INF 的配置信息.
javapoet:用于生成java.class文件

强烈推荐:
https://www.jianshu.com/p/7af58e8e3e18
https://blog.csdn.net/hj7jay/article/details/52180023
https://www.jianshu.com/p/2d6fdbb6ead2
https://blog.csdn.net/qq_27070117/article/details/82873351
https://blog.csdn.net/ai_te_xiao/article/details/79374546
https://blog.csdn.net/ddxxii/article/details/85143830

注解处理器(Annoation Processor)相关推荐

  1. Kotlin版注解处理器Annotation Processor

    文章目录 什么是注解 创建注解 什么是注解处理器 编写注解处理器 使用注解处理器生成代码 在Android项目中使用注解处理器 调试注解处理器 在处理器中记录日志和处理错误 分析种类.数据类型和可见性 ...

  2. JAVA 注解 processor_注解处理器(Annotation Processor)简析

    概念 注解处理器(Annotation Processor)是javac内置的一个用于编译时扫描和处理注解(Annotation)的工具.简单的说,在源代码编译阶段,通过注解处理器,我们可以获取源文件 ...

  3. 【Android 组件化】路由组件 ( 注解处理器参数选项设置 )

    文章目录 一.注解处理器 接收参数设置 二.注解处理器 生成路由表 Java 代码 三.博客资源 组件化系列博客 : [Android 组件化]从模块化到组件化 [Android 组件化]使用 Gra ...

  4. 【错误记录】Android 编译时技术报错 ( 注解处理器 process 方法多次调用问题 )

    文章目录 一.报错信息 二.问题分析 三.解决方案 注解处理器 AbstractProcessor 中的 process 方法可能会调用多次 , 在生成代码时 , 一定要注意 , 检测到 注解节点 后 ...

  5. 【Android 组件化】路由组件 ( 注解处理器获取被注解的节点 )

    文章目录 一.设置支持的注解类型 二.注解处理器中打印日志 三.主应用中使用注解 四.注解处理器 获取注解节点 五.博客资源 组件化系列博客 : [Android 组件化]从模块化到组件化 [Andr ...

  6. 【错误记录】Android 编译时技术版本警告 ( 注解处理器与主应用支持的 Java 版本不匹配 )

    文章目录 一.报错信息 二.问题分析 三.解决方案 一.报错信息 在使用 Android 编译时技术 , 涉及 编译时注解 , 注解处理器 ; 开发注解处理器后 , 编译报如下警告 ; 该警告不会影响 ...

  7. 【Android APT】注解处理器 ( 根据注解生成 Java 代码 )

    文章目录 一.生成 Java 代码 二.实现 IButterKnife 接口 三.视图绑定主要操作 四.完整注解处理器代码 五.博客资源 Android APT 学习进阶路径 : 推荐按照顺序阅读 , ...

  8. 【Android APT】注解处理器 ( Element 注解节点相关操作 )

    文章目录 一.获取被 注解 标注的节点 二.Element 注解节点类型 三.VariableElement 注解节点相关操作 四.注解处理器 完整代码示例 五.博客资源 Android APT 学习 ...

  9. 【Android APT】注解处理器 ( 注解标注 与 初始化方法 )

    文章目录 一.注解处理器 AbstractProcessor 二.使用注解 @AutoService(Processor.class) 标注 注解处理器 三.注解处理器 init 初始化方法 四.注解 ...

  10. Java注解处理器使用详解

    文章转自:http://www.race604.com/annotation-processing/ 在这篇文章中,我将阐述怎样写一个注解处理器(Annotation Processor).在这篇教程 ...

最新文章

  1. Web 开发人员必备的随机 JSON 数据生成工具
  2. linux下查看文件编码及修改编码
  3. Linux Shell脚本编程--grep命令
  4. 定时任务提交spark到yarn出现一直accepted以及yarn出现unhealthy情况
  5. pearsonr() python_十分钟搞懂“Python数据分析”
  6. java 中时间计算_java中关于时间的计算
  7. 基于环信sdk的陌生人交友php服务器代码开源
  8. 为什么php不能用了,为什么php不能做大型系统?
  9. 2021 年最佳 JavaScript 框架
  10. 过去一年,被我们“高估”的技术清单
  11. java打印堆栈信息linux,在C/C++程序里打印调用栈信息(转载)
  12. java 虚拟机常用启动参数
  13. 数据结构——栈(链栈)
  14. Photoshop制作banner步骤过程
  15. 星际争霸2的AI环境搭建
  16. 酷睿i7 12700k核显相当于什么显卡 i712700k参数 i7 12700k什么水平
  17. PHP header网页安全认证
  18. 拥有有趣灵魂的程序员们,程序员访谈(四)
  19. 企业私域直播可以应用于哪些场景?
  20. Android Notification 详解(各版本对比)——基本操作

热门文章

  1. 5G系统——5G-GUTI、5G-TMSI、5G-S-TMSI
  2. pageadmin CMS网站制作教程:栏目单页内容如何修改
  3. 数码数字字体_2020年最佳创意数字艺术软件
  4. Spamhaus -影响最大的RBL(实时黑名单列表)服务提供商,非营利性组织
  5. Apache Hudi调研小记
  6. matlab距离平方和公式推导,lstopt 非线性拟合:相关系数之平方(R^2)和决定系数(DC)计算公式是?...
  7. 使用Python对GIF读取、生成、压缩和加水印
  8. 《拆掉思维里的墙》读书笔记
  9. 一直又爱又恨的jqueryValidate,看到一个还不错的laber.error样式
  10. 区块链经济:机构加密经济学的初学者指南