一、注解器
java 注解编译处理器,主要作用是针对特定的注解进行相应的处理。根据个人观察目前主要多用于代码生成、代码审查。在安卓开发中,常用的Butterknife、Dagger2、Room等以及一些组件化的框架都都会看到编译注解处理器的身影。而在java后端的开发中 Lombok 也是有使用到边缘处理器的。
关于注解的定义及分类的大概信息如下图,图片来源于 https://blog.csdn.net/asd54090/article/details/80920667 , 感谢前辈大佬的整理。
二、认识AbstractProcessor
注解处理器(Annotation Processor) 是javac 的一个工具,主要是在编译时扫描和处理由注解。那么我们要处理特定的注解,自然是上不了注解处理器,想要自定义注解处理器处理特定的逻辑和代码,那么就应该继承 AbstractProcessor
这个抽象类,并实现 process
方法。
AbstractProcessor
类的主要几个方法如下:
init(ProcessingEnvironment env)
:由注解工具调用,并传入ProcessingEnvironment
参数,ProcessingEnvironment
提供很多工具类Messager
、Types
、Elements
、Filer
等等。process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
:每个处理器的核心处理业务都在这里得到执行,可以实现代码扫描、评估、注释代码处理,生成java文件。通过参数RoundEnvironment
的getElementsAnnotatedWith
可以获取到特定注解的元素。getSupportedSourceVersion()
:主要用来指定处理器支持处理的Java版本,通常使用SourceVersion.latestSupported()
作为返回值。当然如果自定义注解类使用了@SupportedSourceVersion
注解,可以不用重写此方法。注意:如果使用
@SupportedSourceVersion
注解,需要考虑,这个注解是 java 6 才引入的getSupportedAnnotationTypes()
: 主要是用来设置当前注解处理器支持处理的注解,如果不指定需要处理的注解,则process
方法将不会得到执行。该方法返回的是Set<String>
集合,包含支持注解的合法全称。注意:该方法也可以使用
@SupportedAnnotationTypes
注解来代替。
三、自定义 Annotation Processor
实现自定义注解大概分为以下这几个步骤:
step1、定义注解;
step2、继承 AbstractProcessor 类并实现抽象方法 process
和重新上面介绍到的另外几个方法;
step3、编写关键的业务代码逻辑,主要在逻辑应写在 process
方法中;比如解析语法树,编辑修改、增加语法树等等
(关于语法树,本次不做记录和解释,后面再新的篇幅另做介绍。)
新建工程,maven 依赖如下:
1 | <dependencies> |
- AutoService 会自动在META-INF文件夹下生成Processor配置信息文件,该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定,方便快捷。
如果不依赖 auto-service
时,则需要在 META-INF\services
文件夹下手动创建 javax.annotation.processing.Processor
文件。并且保存自定义注解器的包路径,如:com.godc.XAnnotionProcessor
- tools 依赖包是jdk 自带的工具包,语法树相关的都会用到该依赖。比如:JCTree、TreeMaker
首先定义一个注解,比如一个方法注解,在注解的方法中添加日志打印
1 | package com.godc.annotation; |
自定义处理器类如下
1 | package com.godc; |
编写测试方法,并使用注解,编译项目就会得到如下效果
四、调试注解器
在 IDEA中调试编译注解器还是挺方便的,IDEA作为客户端,JVM作为服务端。主要三个步骤:
- 在注解器中打断点
- 在IDEA (Edit Configurations)中配置远程调试 (如下图3)
- 在 terminal 控制台输入
mvnDebug clean package
,打开maven 远程调试服务监听 8000 端口了 - 点击debug 按钮 启动远程调试
在此次的测试中,项目结构如下图:
mprocessor
为注解器模块,存放注解、注解器的实现,代码生成
testprocessor
为测试模块,依赖 注解器模块 做测试
资源来源:
https://blog.csdn.net/asd54090/article/details/80920667
https://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/AbstractProcessor.html
https://blog.csdn.net/dap769815768/article/details/90448451