JSR 269(Pluggable Annotation Processing API)提供一套标准API来使用 Annotation Processor 在编译期间而不是运行期间处理Annotation ,相当于编译器的一个插件,是 JDK 6 的一个新特性。
本文只是一个 Hello Word 的示例,效果只是在使用 javac 编译的时候在控制台输出一句话。如果想实现类似于 lombok 在编译期通过注解修改原有类文件的效果,可以查看最后参考资料里面的链接。
元注解回顾
在了解 JSR-269 之前,先了解一下 注解的注解 —— 元注解(用来描述注解的注解)
@Target
定义注解可使用的地方
1 | public enum ElementType { |
@Retention
1 | public enum RetentionPolicy { |
@Documented
声明该注解应包含在 javadoc 中
@Inherited
使用此注解声明出来的自定义注解,在使用此自定义注解时,如果注解在类上面时,子类会自动继承此注解,否则的话,子类不会继承此注解
注解处理器(Annotation Processor)
JSR 269 的核心是 Annotation Processor 即注解处理器,与运行时注解RetentionPolicy.RUNTIME
不同,注解处理器只会处理编译期注解,也就是RetentionPolicy.SOURCE
的注解类型,处理的阶段位于Java代码编译期间。
如果 Annotation Processor 处理 Annotation 时产生了新的Java代码,编译器会再调用一次Annotation Processor,如果第二次处理还有新代码产生,就会接着调用Annotation Processor,直到没有新代码产生为止。
使用步骤
- 自定义一个注解,注解的元注解需要指定
@Retention(RetentionPolicy.SOURCE)
- 创建 注解处理器类 继承
javax.annotation.processing.AbstractProcessor
,并覆写process
方法- 在创建的注解处理器类上使用
javax.annotation.processing.SupportedAnnotationTypes
注解指定 自定义注解的全名 - 在创建的注解处理器类上使用
javax.annotation.processing.SupportedSourceVersion
注解指定编译版本 - 【可选】在创建的注解处理器类上使用
javax.annotation.processing.SupportedOptions
注解指定编译参数
- 在创建的注解处理器类上使用
示例
S1. 编写 自定义注解
1 | package xyz.kail.demo; |
S2. 创建 注解处理器类
1 | package xyz.kail.demo; |
S3. 启动类
1 | package xyz.kail.demo; |
S4. 编译 注解处理器类
在使用 javac 编译的时候,注解处理器类 必须事先已经被编译过了,所需要先编译 HelloAnnotationProcessor:
1 | javac xyz/kail/demo/HelloAnnotationProcessor.java |
S5. 编译 被自定义注解修饰的类
请注意 -processor
参数,用来指定注解处理器
1 | javac -processor xyz.kail.demo.HelloAnnotationProcessor xyz/kail/demo/Main.java |
编译时输出如下:
1 | Hello World |
启用注解处理器的几种方式
在编译时启用注解处理器 除了 -processor
参数外,还有以下两种常见方式
SPI 服务提供者发现机制
就是把注解处理器事先打成 jar 包,并在 jar 包内的 META-INF/services/
文件夹内包含 文件 javax.annotation.processing.Processor
,文件内容是 注解处理器的全路径名(xyz.kail.demo.HelloAnnotationProcessor
)
1 | xxx.jar |
Maven
1 | <plugin> |