注解使用apt处理注解
【摘要】 背景最近在研究mapStruct,而mapStruct核心技巧就是apt,通过编译期注解+freemarker进行java文件生成,从而省去了很多编码。本wiki将阐述一个apt的编程实践。实践过程创建一个hello工程工程由两个模块组成:application模块,将使用自定义的编译器注解apt模块,自定义注解,并且完成AbstractProcessor的继承和实现根pom如下:<?xml...
背景
最近在研究mapStruct,而mapStruct核心技巧就是apt,通过编译期注解+freemarker进行java文件生成,从而省去了很多编码。
本wiki将阐述一个apt的编程实践。
实践过程
创建一个hello工程
工程由两个模块组成:
- application模块,将使用自定义的编译器注解
- apt模块,自定义注解,并且完成AbstractProcessor的继承和实现
根pom如下:
<?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>com.mine</groupId>
<artifactId>apt-test</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>application</module>
<module>apt</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
</project>
application的pom如下
<?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">
<parent>
<artifactId>apt-test</artifactId>
<groupId>com.mine</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>application</artifactId>
<dependencies>
<dependency>
<groupId>com.mine</groupId>
<artifactId>apt</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
apt的pom如下
<?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">
<parent>
<artifactId>apt-test</artifactId>
<groupId>com.mine</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<artifactId>apt</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建一个Main类,并且运行一下看看结果
编写apt代码
自定义一个注解
实现AbstractProcessor,实现process过程
package com.mine.processor;
import com.mine.anno.CustomAnnotation;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
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;
@SupportedAnnotationTypes({
"com.mine.anno.CustomAnnotation"
})
public class MyProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
//然后文件会被解释为.class文件
StringBuilder builder = new StringBuilder()
.append("package com.mine.annotationprocessor.generated;\n\n")
.append("public class GeneratedClass {\n\n")
.append("\tpublic String getMessage() {\n")
.append("\t\treturn \"");
//获取所有被CustomAnnotation修饰的代码元素
for (Element element : roundEnv.getElementsAnnotatedWith(CustomAnnotation.class)) {
String objectType = element.getSimpleName().toString();
builder.append(objectType).append(" exists!\\n");
}
builder.append("\";\n")
.append("\t}\n")
.append("}\n");
try {
JavaFileObject source = processingEnv.getFiler().createSourceFile(
"com.mine.annotationprocessor.generated.GeneratedClass");
Writer writer = source.openWriter();
writer.write(builder.toString());
writer.flush();
writer.close();
} catch (IOException e) {
//
}
return false;
}
}
过程很简单,通过StringBuilder来写一个java文件
配置resources
在resources/META-INF/services/创建javax.annotation.processing.Processor
内容为:
com.mine.processor.MyProcessor
这里表示,java compile编译器会通过配置文件去找到对应的processor,进行编译期的调用
编写application代码
创建一个DemoClass类
package com.mine;
import com.mine.anno.CustomAnnotation;
// 使用我们自定义的注解
@CustomAnnotation
public class DemoClass {
}
创建一个MyModel类
package com.mine;
import lombok.Data;
// 使用lombok的Data,这里也可以自动生成代码
@Data
public class MyModel {
private String name;
private Integer age;
}
编译
在根目录执行mvn compile
或者直接使用idea执行
查看class字节码文件的生成情况
可以看到已经有我们生成的代码了
MyModel使用了lombok,可以自动生成get set和toString等方法
评价
通过apt可以生成很多方便的代码生成模板,比如mapStruct,lombok等。可以参考博主的其他博客查看mapStruct的使用。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)