跳至主要內容

Java注解处理器、语法树修剪

DHB大约 2 分钟Java

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对象

资料

java注解处理器——在编译期修改语法树open in new window

annotationProcessor 自动生成代码(上)open in new window

annotationProcessor 自动生成代码(下)open in new window

编译期修改Classopen in new window

Lombok原理分析与功能实现open in new window

Compiler Tree Apiopen in new window

上次编辑于:
贡献者: dhb