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 如下图:

以下是一个简单的示例,演示如何使用 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
创建的动态代码如下图:
