编译期修改 AST,实现对类的增强
1. 新建项目
IDEA 新建项目,再创建两个子 module,core 为处理器,sample 为测试样例,目录结构:
demo
├── core
│ ├── src
│ │ └── main
│ │ ├── java
│ │ └── resources
│ └── pom.xml
├── sample
│ ├── src
│ │ └── main
│ │ ├── java
│ │ └── resources
│ └── pom.xml
└── pom.xml
启用注解处理器:
Preferences → Build, Execution, Deployment → Compiler → Annotation Processors → Enable annotation Processing
如果项目编译报错,需要在 IDEA 设置里配置
Build, Execution, Deployment → Compiler → Shared build process VM options
-Djps.track.ap.dependencies=false
2. core 模块
-
POM 文件修改
<version>1.0-SNAPSHOT</version>s <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <auto.service.version>1.0.1</auto.service.version> </properties> <dependencies> <dependency> <groupId>com.google.auto.service</groupId> <artifactId>auto-service-annotations</artifactId> <version>${auto.service.version}</version> <optional>true</optional> <scope>compile</scope> </dependency> <dependency> <groupId>com.google.auto.service</groupId> <artifactId>auto-service</artifactId> <version>${auto.service.version}</version> <optional>true</optional> <scope>compile</scope> </dependency> <dependency> <groupId>sun.jdk</groupId> <artifactId>tools</artifactId> <version>${java.version}</version> <scope>system</scope> <optional>true</optional> <systemPath>${java.home}/../lib/tools.jar</systemPath> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <annotationProcessorPaths> <path> <groupId>com.google.auto.service</groupId> <artifactId>auto-service</artifactId> <version>${auto.service.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
auto-service
用于编译时自动生成
META-INF/services/javax.annotation.processing.Processor
,这一部分涉及到 Java SPI 的内容,此处不做详细介绍。 -
定义注解
@Retention(RetentionPolicy.SOURCE) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface Log { }
因为处理器是在编译期生效,所以 Retention 定义为
RetentionPolicy.SOURCE
即可。 -
定义处理器
Java 中的注解处理器接口为
javax.annotation.processing.Processor
,实际开发中通常会继承javax.annotation.processing.AbstractProcessor
这个抽象类。@AutoService(Processor.class) @SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes("org.example.ast.Log") public class LogProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "测试处理器"); return false; } }
3. sample 模块
-
POM 文件修改
在
sample
中依赖core
:<dependencies> <dependency> <groupId>org.example</groupId> <artifactId>core</artifactId> <version>1.0-SNAPSHOT</version> <scope>provided</scope> </dependency> </dependencies>
-
创建测试类
@Log public class Main { public static void main(String[] args) { } }
编译项目,在 IDEA 下面的 Build 窗口中查看信息:
... Parsing java… [sample] java: 测试处理器 Writing classes… [sample] ...
LogProcessor
中的日志已经打印,说明注解处理器被成功加载
4. Debug 编译流程
在项目中创建 Remote JVM Debug,端口号改为 8000
在项目中根目录,执行命令
mvnDebug clean compile
终端中显示
Preparing to execute Maven in debug mode
Listening for transport dt_socket at address: 8000
项目中点击图中红色 Debug 按钮,即可启用调试
5. 下载 Javac 源码
下载最新的源码,在 IDEA 中任意一个 Javac 中的 class 文件 中点击 Choose Sources,选中刚下载完解压后的文件夹,仅导入src/share/classes/
即可