jdk:17
核心工程
- 創(chuàng)建一個編譯期注解
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
我在這里獲取了被注解函數(shù)的信息,生成了一個類文件
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 當(dāng)前和上一次循環(huán)的信息的環(huán)境
* @return
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
System.out.println("---> ZtestAnnotationProcessor process...");
for (TypeElement annotation : annotations) {
// 獲取所有被該注解 標(biāo)記過的實例
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 表示 當(dāng)前處理器處理了之后 其他的處理器也可以接著處理卖鲤,返回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文件夾下創(chuàng)建一個名為javax.annotation.processing.Processor的文件弹沽;里面的內(nèi)容就是你的注解處理器的全限定類名
- 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>
<!-- 設(shè)置編譯期間禁止處理 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>
- 創(chuàng)建函數(shù)使用定義好的注解
public class ProccesserTest {
@Ztest
public String testAnnotation() {
return "hello";
}
}
- 反射調(diào)用生成的類
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);
}
}
}