java高级特性 - APT
转载于:https://blog.csdn.net/kxkkl/article/details/119152813
准备
开始之前,需要引入jar包,一个是谷歌的工具包,帮助我们自动生成META-INF目录下的配置,另一个是生成class文件的工具
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service</artifactId>
<version>1.0-rc2</version>
</dependency>
<dependency>
<groupId>com.squareup</groupId>
<artifactId>javapoet</artifactId>
<version>1.13.0</version>
</dependency>
开始
首先创建一个自定义注解,用于注解处理器识别,代码如下:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Hello {
}
然后创建注解处理器类,代码如下:
import com.google.auto.service.AutoService;
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
import java.util.Set;
@AutoService(Processor.class)
@SupportedAnnotationTypes("com.lushwe.Hello")
@SupportedSourceVersion(value = SourceVersion.RELEASE_8)
public class HelloAnnotationProcessor extends AbstractProcessor {
private Elements elementUtils;
private Types typeUtils;
private Filer filer;
private Messager messager;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
elementUtils = processingEnvironment.getElementUtils();
typeUtils = processingEnvironment.getTypeUtils();
messager = processingEnvironment.getMessager();
filer = processingEnvironment.getFiler();
}
@Override
@SneakyThrows
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (set.isEmpty()) {
return false;
}
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(Hello.class);
for (Element element : elements) {
parseElement(element);
}
return true;
}
private void parseElement(Element element) throws Exception {
String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
String className = element.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE, "=HelloProcessor=" + packageName + "/" + className);
FieldSpec id = FieldSpec.builder(Long.class, "id")
.addModifiers(Modifier.PRIVATE)
.addJavadoc("ID")
.build();
FieldSpec name = FieldSpec.builder(String.class, "name")
.addModifiers(Modifier.PRIVATE)
.addJavadoc("名称")
.build();
TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Getter.class)
.addAnnotation(Setter.class)
.addField(id)
.addField(name)
.build();
JavaFile javaFile = JavaFile.builder(packageName, typeSpec)
.build();
// 写入
javaFile.writeTo(filer);
}
}
基本已经完成了,打成一个jar(一般都是通过jar引入)
使用
新建一个工程引入上面的jar,查看引入的jar在 META-INF.services 下面有一个 javax.annotation.processing.Processor 配置文件,里面是 com.lushwe.HelloAnnotationProcessor ,这个就是上面引入谷歌jar包 auto-service 自动生成的,不然的需要我们手工创建,虽然都可以,但是麻烦,这样比较方便,详细如图

创建一个配置类,代码注解 @Hello ,否则无法触发注解处理器
@Hello
public class HelloConfig {
}
然后编译即可触发注解处理器,然后就会在target目标自动生成代码
其中 classes 目录下,HelloConfig相同包下会生成 HelloWorld.class 代码如下,其中get set方法是 @Getter @Setter 帮我们创建的
package com.lushwe;
public class HelloWorld {
private Long id;
private String name;
public HelloWorld() {
}
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
其中 generated-sources 目录下,会生成对应的HelloWorld.java代码,方便我们系统里面引入(没有这个代码的话,系统里面引用虽然能运行,但是在idea类似的开发工具里面显示报错,体验不好,注意这里仅仅是方便我们使用,不会像我们自己新增一个类一样要提交),如下:
package com.lushwe;
import java.lang.Long;
import java.lang.String;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class HelloWorld {
/**
* ID
*/
private Long id;
/**
* 名称
*/
private String name;
}
截图证明

补充
本文仅演示了maven,有些使用gradle的小伙伴可能会遇到class文件能正常生成,但是java文件没生成,导致系统使用该类的地方报错,但是不影响编译、也能正常运行,不过体验不好,使用gradle的小伙伴,检查下面的配置是否有,没有添加下即可
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
// 关键点1
classpath "net.ltgt.gradle:gradle-apt-plugin:0.21"
}
}
// 关键点1
apply plugin: "net.ltgt.apt-idea"
上面配置来自gradle 插件官网
本文来自博客园,作者:蓝迷梦,转载请注明原文链接:https://www.cnblogs.com/hewei-blogs/articles/17601394.html

浙公网安备 33010602011771号