边肖,让我们与你分享java中javac抽象处理器的使用。希望大家看完这篇文章后有所收获。我们一起讨论一下吧!
00-1010当然,它做的是生成新的类或者修改原来的类。例如,您可以在遇到这种情况时使用它:
反思是如此缓慢。我在一家大工厂见过大量的Gson。因为Gson在序列化中广泛使用反射,所以每个字段和每个get和set都需要反射,这会带来性能问题。解决方案是使用它来最小化反射(用JSONObject替换)
生成的代码可以在有注释的地方阅读,简而言之,有很多(一些android orm框架)
00-1010 javax . annotation . processing . processing处理器接口会提供注释处理,根据SPI协议进行扩展,jdk默认有很多处理器。
00-1010注释处理器是最重要的扩展处理类。
注意:请确保已经成功配置了JAVA的环境变量,并将tools.jar(来自这个包)添加到自己计算机的环境变量中。
ProcessingEnvironment是注释处理工具的集合。元素是表示程序元素的接口,程序元素可以是包、类、方法或变量。元素的已知子接口有:
PackageElement表示包程序元素。提供对有关包及其成员的信息的访问。
ExecutableElement表示类或接口的方法、构造函数或初始值设定项(静态或实例),包括注释类型元素。
TypeElement表示类或接口程序元素。提供对有关类型及其成员的信息的访问。请注意,枚举类型是一种类型,而注释类型是一种接口。
元素表示字段、枚举常量、方法或构造函数参数、局部变量或异常参数。00-1010关注过程方法
//来自javax . annotation . processing;
publicatabstractclass abstractprocessoriimplements processor {
//集合中指定的支持的注释类型的名称(这里必须是完整的包名类名)
public setstringsetsupportedannotationtypes(){ 0
supportedannocationtypessat=this . getclass()。getAnnotation(supportedannotationtypes . class);
if(sat==null){ 0
if(isInitialized())
processingEnv.getMessager()。打印消息(诊断。善良。警告,
(=NationalBureauofStandards)国家标准局
p; "No SupportedAnnotationTypes annotation " +
"found on " + this.getClass().getName() +
", returning an empty set.");
return Collections.emptySet();
}
else
return arrayToSet(sat.value());
}
// 指定当前正在使用的Java版本
public SourceVersion getSupportedSourceVersion() {
SupportedSourceVersion ssv = this.getClass().getAnnotation(SupportedSourceVersion.class);
SourceVersion sv = null;
if (ssv == null) {
sv = SourceVersion.RELEASE_6;
if (isInitialized())
processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
"No SupportedSourceVersion annotation " +
"found on " + this.getClass().getName() +
", returning " + sv + ".");
} else
sv = ssv.value();
return sv;
}
// 初始化处理器
public synchronized void init(ProcessingEnvironment processingEnv) {
if (initialized)
throw new IllegalStateException("Cannot call init more than once.");
Objects.requireNonNull(processingEnv, "Tool provided null ProcessingEnvironment");
this.processingEnv = processingEnv;
initialized = true;
}
/**
* 这些注解是否由此 Processor 处理,该方法返回ture表示该注解已经被处理, 后续不会再有其他处理器处理; 返回false表示仍可被其他处理器处理
*/
public abstract boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv);
}
实现一个打印可以API的功能
由于本人是maven环境,以此展开讲
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <!--Disable annotation processing for ourselves--> <!--<compilerArgument>-proc:none</compilerArgument>--> </configuration> </plugin> </plugins> </build>
步骤1:实现一个注解处理器
@Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE, ElementType.METHOD}) public @interface ApiAnnotation { String author() default "alex.chen"; String date(); int version() default 1; } @SupportedAnnotationTypes({"com.kxtx.annotation.ApiAnnotation"}) @SupportedSourceVersion(SourceVersion.RELEASE_8) //@AutoService(Processor.class) public class MyProcessor extends AbstractProcessor { //类名的前缀、后缀 public static final String SUFFIX = "AutoGenerate"; public static final String PREFIX = "My_"; @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { Messager messager = processingEnv.getMessager(); for (TypeElement typeElement : annotations) { for (Element e : env.getElementsAnnotatedWith(typeElement)) { //打印 messager.printMessage(Diagnostic.Kind.WARNING, "Printing:" + e.toString()); messager.printMessage(Diagnostic.Kind.WARNING, "Printing:" + e.getSimpleName()); messager.printMessage(Diagnostic.Kind.WARNING, "Printing:" + e.getEnclosedElements().toString()); //获取注解 ApiAnnotation annotation = e.getAnnotation(ApiAnnotation.class); //获取元素名并将其首字母大写 String name = e.getSimpleName().toString(); char c = Character.toUpperCase(name.charAt(0)); name = String.valueOf(c + name.substring(1)); //包裹注解元素的元素, 也就是其父元素, 比如注解了成员变量或者成员函数, 其上层就是该类 Element enclosingElement = e.getEnclosingElement(); //获取父元素的全类名,用来生成报名 String enclosingQualifiedname; if (enclosingElement instanceof PackageElement) { enclosingQualifiedname = ((PackageElement) enclosingElement).getQualifiedName().toString(); } else { enclosingQualifiedname = ((TypeElement) enclosingElement).getQualifiedName().toString(); } try { //生成包名 String generatePackageName = enclosingQualifiedname.substring(0, enclosingQualifiedname.lastIndexOf(".")); // 生成的类名 String genarateClassName = PREFIX + enclosingElement.getSimpleName() + SUFFIX; //创建Java 文件 JavaFileObject f = processingEnv.getFiler().createSourceFile(genarateClassName); // 在控制台输出文件路径 messager.printMessage(Diagnostic.Kind.WARNING, "Printing: " + f.toUri()); Writer w = f.openWriter(); try { PrintWriter pw = new PrintWriter(w); pw.println("package " + generatePackageName + ";"); pw.println("\npublic class " + genarateClassName + " { "); pw.println("\n /** 打印值 */"); pw.println(" public static void print" + name + "() {"); pw.println(" // 注解的父元素: " + enclosingElement.toString()); pw.println(" System.out.println(\"代码生成的路径: " + f.toUri() + "\");"); pw.println(" System.out.println(\"注解的元素: " + e.toString() + "\");"); pw.println(" System.out.println(\"注解的版本: " + annotation.version() + "\");"); pw.println(" System.out.println(\"注解的作者: " + annotation.author() + "\");"); pw.println(" System.out.println(\"注解的日期: " + annotation.date() + "\");"); pw.println(" }"); pw.println("}"); pw.flush(); } finally { w.close(); } } catch (IOException e1) { processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e1.toString()); } } } return true; } }
步骤2:配置一个spi,在resources目录新建META-INF/services/javax.annotation.processing.Processor,内容为MyProcessor类全名。
步骤3:在另一个项目中使用@ApiAnnotation就会发现生成了一个新My_feignAutoGenerate.class文件:
public class My_feignAutoGenerate { public My_feignAutoGenerate() { } public static void printStartUp() { System.out.println("代码生成的路径: file:/C:/Users/Administrator/Desktop/feign-async-master/target/generated-sources/annotations/My_feignAutoGenerate.java"); System.out.println("注解的元素: com.github.feign.StartUp"); System.out.println("注解的版本: 1"); System.out.println("注解的作者: alex"); System.out.println("注解的日期: 2019-03-6"); } }
到这里基本上已经演示完了。
google的 auto-service
<dependency> <groupId>com.google.auto.service</groupId> <artifactId>auto-service</artifactId> <version>1.0-rc2</version> </dependency>
这个类库非常有用,它非常简单,使用@AutoService(Processor.class)会基于该接口和注解的类上自动帮我们生成META-INF/services下对应spi文件。它实现的原理就是通过注解处理器。
javapoet
有没有觉得上面pw.println("package " + generatePackageName + ";");这样的代码很痛苦啊?
JavaPoet is a Java API for generating .java source files.
package com.example.helloworld; public final class HelloWorld { public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); } }
MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class) .addParameter(String[].class, "args") .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") .build(); TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addMethod(main) .build(); JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld) .build(); javaFile.writeTo(System.out);
你喜欢的lombok实现原理是怎样的呢?
lombok(用来帮助开发人员消除 Java 对象 的冗长),非常好用
看完了这篇文章,相信你对“java中javac AbstractProcessor有什么用”有了一定的了解,如果想了解更多相关知识,欢迎关注行业资讯频道,感谢各位的阅读!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/77263.html