Java 工具集教程

apt.exe 注解处理器

apt.exe 是 Java SE 5 中新增的一个工具,它是 Annotation Processing Tool(APT)的缩写。APT 工具可以用来处理 Java 代码中的注解,并生成新的 Java 代码。APT 工具可以自动化生成代码,减少手动编写代码的工作量,提高代码的可读性和可维护性。

命令格式

以下是 apt.exe 命令语法:

apt -processor <processor_class> <source_files>

其中:

  • -processor <processor_class>  指定要使用的注解处理器类。

  • <source_files>  指定要处理的源文件。

请注意,APT 工具需要 JDK 5 或 JDK 6 来运行。在 JDK 7 及更高版本中,apt.exe 已经被 javac 工具所取代,可以通过 javac 的 -processor 选项来指定注解处理器。或者,使用 javax.annotation.processing API 和自定义注解处理器来代替 APT 工具。API 如下图:

apt.exe 注解处理器

命令示例

以下是一个简单的示例,演示如何使用 javac 的 -processor 注解处理器来处理自定义注解。

简单示例

(1)定义一个自定义注解 @MyAnnotation:

package com.hxstrive.apt;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义一个注解
 * @author HuangXin
 * @since 1.0.0  2024/2/28 10:09
 */
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface MyAnnotation {

    String value();

}

(2)创建一个注解处理器 MyAnnotationProcessor:

package com.hxstrive.apt;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;

/**
 * 注解处理器
 * @author HuangXin
 * @since 1.0.0
 */
// 指定该注解处理器可以解决的类型,需要完整的包名+类命
@SupportedAnnotationTypes("com.hxstrive.apt.MyAnnotation")
// 指定编译的JDK版本
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyAnnotationProcessor extends AbstractProcessor {

    // 这里就是处理注解的process函数
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        System.out.println("=======================");
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing annotations...");
        for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
            MyAnnotation annotation = element.getAnnotation(MyAnnotation.class);
            String value = annotation.value();
            processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Found @MyAnnotation with value: " + value);
        }
        return true;
    }

}

(3)创建一个测试类 TestClass,并在方法上使用 @MyAnnotation 注解:

package com.hxstrive.apt;

/**
 * 测试类
 * @author HuangXin
 * @since 1.0.0
 */
public class TestClass {

    @MyAnnotation("Hello, Annotation Processing!")
    public void testMethod() {
        System.out.println("This is a test method.");
    }

}

编译方式一:

(1)使用不带有 -processor 的 javac 命令编译注解处理器,例如:

E:\demo\src\main\java>javac -encoding UTF-8 -cp .;./classes -d classes ./com/hxstrive/apt/*.java

(2)使用带有 -processor 编译代码,例如:

E:\demo\src\main\java>javac -encoding UTF-8 -cp .;./classes -processor com.hxstrive.apt.MyAnnotationProcessor ./com/hxstrive/apt/TestClass.java
=======================
注: Processing annotations...
注: Found @MyAnnotation with value: Hello, Annotation Processing!
=======================
注: Processing annotations...

编译方式二:

(1)在源码根目录下面创建 META-INF\services\javax.annotation.processing.Processor 文件,文件内容为自定义注解处理器的完全限定类名 com.hxstrive.apt.MyAnnotationProcessor。

(2)使用不带 -processor 的 javac 命令编译源码,如下:

E:\demo\src\main\java>javac -encoding UTF-8 -cp .;./classes -d classes ./com/hxstrive/apt/*.java
=======================
注: Processing annotations...
注: Found @MyAnnotation with value: Hello, Annotation Processing!
=======================
注: Processing annotations...

通过输出可知,注解处理器已经被触发了。

动态创建代码

下面将利用注解处理器动态创建代码:

(1)定义一个自定义注解 @MyAnnotation:

package com.hxstrive.apt2;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义一个注解
 * @author HuangXin
 * @since 1.0.0  2024/2/28 10:09
 */
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface MyAnnotation {

    String value();

}

(2)创建一个注解处理器 MyAnnotationProcessor:

package com.hxstrive.apt2;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.io.Writer;
import java.util.Set;

/**
 * 注解处理器
 * @author HuangXin
 * @since 1.0.0
 */
// 指定该注解处理器可以解决的类型,需要完整的包名+类命
@SupportedAnnotationTypes("com.hxstrive.apt2.MyAnnotation")
// 指定编译的JDK版本
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyAnnotationProcessor extends AbstractProcessor {

    // 这里就是处理注解的process函数
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // 创建动态代码,实际上就是创建一个String, 写入到文件里
        // 然后文件会被解释为.class文件
        StringBuilder builder = new StringBuilder()
                .append("package com.hxstrive.apt2;\n\n")
                .append("public class GeneratedClass {\n\n")
                .append("\tpublic String getMessage() {\n")
                .append("\t\treturn \"");

        // 获取所有被 MyAnnotation 修饰的代码元素
        for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
            String objectType = element.getSimpleName().toString();
            builder.append(objectType).append(" exists!\\n");
        }
        builder.append("\";\n")
                .append("\t}\n")
                .append("}\n");

        // 将String写入并生成.class文件
        try {
            JavaFileObject source = processingEnv.getFiler().createSourceFile(
                    "com.hxstrive.apt2.GeneratedClass");
            Writer writer = source.openWriter();
            writer.write(builder.toString());
            writer.flush();
            writer.close();
        } catch (IOException e) {
            //
        }

        return true;
    }

}

(3)创建一个测试类 TestClass,并在方法上使用 @MyAnnotation 注解:

package com.hxstrive.apt2;

/**
 * 测试类
 * @author HuangXin
 * @since 1.0.0
 */
public class TestClass {

    @MyAnnotation("Hello, Annotation Processing!")
    public void testMethod() {
        System.out.println("This is a test method.");
    }

}

运行如下命令:

# 编译注解处理器
E:\demo\src\main\java>javac -encoding UTF-8 -cp .;./classes -d classes ./com/hxstrive/apt2/*.java

# 触发注解处理器
E:\demo\src\main\java>javac -encoding UTF-8 -cp .;./classes -processor com.hxstrive.apt2.MyAnnotationProcessor ./com/hxstrive/apt2/TestClass.java

创建的动态代码如下图:

apt.exe 注解处理器

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号