jdk:17
核心工程
- 创建一个编译期注解
package org.example;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Jenson
* @version 1.0
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface Ztest {
}
- 具体的逻辑代码,继承
AbstractProcessor
我在这里获取了被注解函数的信息,生成了一个类文件
package org.example;
import javax.annotation.processing.*;
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.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author Jenson
* @version 1.0
* @date 2023-10-18 11:28
*/
@SupportedAnnotationTypes("org.example.Ztest")
public class ZtestAnnotationProcessor extends AbstractProcessor {
/**
* @param annotations the annotation interfaces requested to be processed 请求处理注解类型的集合
* @param roundEnv environment for information about the current and prior round 当前和上一次循环的信息的环境
* @return
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
System.out.println("---> ZtestAnnotationProcessor process...");
for (TypeElement annotation : annotations) {
// 获取所有被该注解 标记过的实例
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
List<String> names = new ArrayList<>();
for (Element annotatedElement : annotatedElements) {
System.out.println("--> " + annotatedElement.getSimpleName().toString());
names.add("\"" + annotatedElement.getSimpleName().toString() + "\"");
}
StringBuilder namesStr = new StringBuilder();
if (!names.isEmpty()) {
for (int i = 0; i < names.size(); i++) {
if (i == 0) {
namesStr = new StringBuilder(names.get(i));
} else {
namesStr.append(",").append(names.get(i));
}
}
}
String packageName = "org.example";
String className = "AnnotationClassName";
try {
JavaFileObject builderFile = processingEnv.getFiler()
.createSourceFile(packageName + "." + className);
try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
out.print("package ");
out.print(packageName);
out.println(";");
out.println();
out.print("public class ");
out.print(className);
out.println(" {");
out.println();
out.println(" public AnnotationClassName() {}");
out.println();
out.println(" public static String[] outNames() {");
out.println(" return new String[]{" + namesStr + "};");
out.println(" }");
out.println("}");
}catch (Exception e){
System.out.println("----> errorrrrrrrr 2");
}
} catch (IOException e) {
System.out.println("----> errorrrrrrrr 1");
throw new RuntimeException(e);
}
}
// 返回false 表示 当前处理器处理了之后 其他的处理器也可以接着处理,返回true表示,我处理完了之后其他处理器不再处理
return false;
}
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
System.out.println("----------");
System.out.println(processingEnv.getOptions());
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
- 配置SPI
在resource/META-INF.services文件夹下创建一个名为javax.annotation.processing.Processor的文件;里面的内容就是你的注解处理器的全限定类名
- Maven 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>AbstractProcessorTest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<!-- 设置编译期间禁止处理 Process-->
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</execution>
<execution>
<id>compile-project</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 编译打包安装
> mvn install
使用者(新工程)
- 依赖刚才的组件
<dependency>
<groupId>org.example</groupId>
<artifactId>AbstractProcessorTest</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- 创建函数使用定义好的注解
public class ProccesserTest {
@Ztest
public String testAnnotation() {
return "hello";
}
}
- 反射调用生成的类
public class Main {
public static void main(String[] args) {
// ProccesserTest pt = new ProccesserTest();
// System.out.println(pt.testAnnotation());
try {
Class<?> clz = Class.forName("org.example.AnnotationClassName");
Object obj = clz.getDeclaredConstructor().newInstance();
Method method = clz.getMethod("outNames");
method.setAccessible(true);
String[] margs = (String[]) method.invoke(obj);
for (String marg : margs) {
System.out.println(marg);
}
} catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException |
NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}