Java注解处理器、语法树修剪
大约 2 分钟
Java注解处理器、语法树修剪
依赖
- auto-service 方便生成Processor
- qdox 解析java文件
- tools.jar javac工具,修改语法树,也支持遍历javadoc
maven使用tools.jar
<profiles>
<profile>
<id>default-tools.jar</id>
<activation>
<property>
<name>java.vendor</name>
<value>Sun Microsystems Inc.</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.8</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
</profile>
</profiles>
autoservice
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.0-rc7</version>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<annotationProcessorPaths>
<path>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.0-rc7</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
编译器
种类
- Javac
- eclipse(ecj)
- Groovy-Eclipse
- Ajc
Java Annotation Processor
javax.annotation.processing.Processor接口有一个实现抽象类AbstractProcessor,默认实现了以下方法,提供注解实现
- Set getSupportedOptions() -- @SupportedOptions
- Set getSupportedAnnotationTypes(); -- @SupportedAnnotationTypes
- SourceVersion getSupportedSourceVersion(); -- @SupportedSourceVersion
注:注解配置降低了代码的复杂度
例子
// 生成配置文件META-INF/services/xxxx
@AutoService(Processor.class)
// 所有注解(必须要声明)
@SupportedAnnotationTypes("*")
// 版本
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class DemoProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
// 如果返回true,不会流到下面的处理器
return false;
}
}
使用Spi
在注解处理器中使用spi,依赖也需要像注解处理器一样的方式引入,不然加载不到
获取JCCompilationUnit
JCCompilationUnit代表一个完整Class
private JCCompilationUnit toUnit(Element element) {
TreePath path = null;
if (trees != null) {
try {
path = trees.getPath(element);
} catch (NullPointerException ignore) {
// Happens if a package-info.java dowsn't conatin a package declaration.
// https://github.com/rzwitserloot/lombok/issues/2184
// We can safely ignore those, since they do not need any processing
}
}
if (path == null) return null;
return (JCCompilationUnit) path.getCompilationUnit();
}
element转tree
com.sun.source.util.Trees
trees = Trees.instance(javacProcessingEnv);
// 获取Tree
tress.getTree(element)
Tree获取element
Tree中的sym变量就是element对象