通过在编译期间,修改Java的AST(Abstract Syntax Tree)树,可以往类中,添加/修改(覆盖)方法、属性等。
现在比较常见的三方依赖例子有:Lobbok的@Data可以生成get、set方法,@Sl4j2可以生成静态常量log。
这篇文章,主要通过代码展示如何生成get、set方法。
import java.lang.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
}
Java 编译器对注解的操作,是通过继承AbstractProcessor来实现的。如下是一个添加setter方法:
流程:
过程代码涉及信息泄密,忽略。
遵循SPI(Service Provider interface),在resources/META-INF/services中配置注解增强器,项目结构结构如下:
先忽略
文件的内容如下,如果有多个增强器,按行配置即可:
incremental.annotation.processors:
com.huawei.fbb.cool.aspect.cool.data.DataProcessor,isolating1
javax.annotation.processing.Processor:
com.huawei.fbb.cool.aspect.cool.data.DataProcessor
参考@Data编译后的class文件
由于是编译时注解,注解增强器,一定要单独一个项目(项目A),然后打包给其它服务引用(项目B)。
项目A的pom:
<dependencies>
<dependency>
<groupId>com.sungroupId>
<artifactId>toolsartifactId>
<version>1.8version>
<scope>systemscope>
<systemPath>${java.home}/../lib/tools.jarsystemPath>
dependency>
dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
<executions>
<execution>
<id>default-compileid>
<configuration>
<compilerArgument>-proc:nonecompilerArgument>
configuration>
execution>
<execution>
<id>compile-projectid>
<phase>compilephase>
<goals>
<goal>compilegoal>
goals>
execution>
executions>
plugin>
plugins>
pluginManagement>
build>
其中关于配置,可以用谷歌的 AutoService
由于往AST插入方法元素,没有判断是否依据存在此类方法,所以很可能覆盖掉之前类中已经存在的方法
增加方法之前,最好先判断一下是否已经含有这个的方法,如果有,就不插入。