区长

编译时注解 5 步走

前言

简单记录一下,编写编译时注解的几个步骤。

新建Java Module

new-module.png

引入auto-service(自动生成services下文件)和javapoet(生成java文件)

1
2
compile 'com.google.auto.service:auto-service:1.0-rc2'
compile 'com.squareup:javapoet:1.8.0'

编写注解

1
2
3
4
5
6
7
8
9
10
11
12
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@Inherited
public @interface Api {

String scope();

String name();

String version();

}

创建AbstractProcessor实现类

重写getSupportedSourceVersion,getSupportedAnnotationTypes和process方法。注意在类上加入注解AutoService,便会自动生成META-INF下的services文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@AutoService(Processor.class)
public class AnnotationProcessor extends AbstractProcessor {

@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}

@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> supportedAnnotationTypes = new HashSet<>();
supportedAnnotationTypes.add(Api.class.getCanonicalName());
return supportedAnnotationTypes;
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return false;
}


}

实现process方法,根据注解生成对应代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Api.class);
for (Element e : elements) {
//获得对应的注解
Api api = e.getAnnotation(Api.class);
System.out.println("*");
//使用javapoet开始生成代码
TypeSpec clazz = TypeSpec.classBuilder(api.name().toUpperCase() + "Request")
.addJavadoc("Generated request for network\n")
.addSuperinterface(Serializable.class)
.build();

JavaFile javaFile = JavaFile.builder("com.funcknmb.api", clazz)
.build();

//生成的代码写入文件
try {
JavaFileObject fileObject = processingEnv.getFiler().createSourceFile("com.funcknmb.api." + api.name().toUpperCase() + "Request");
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Creating " + fileObject.toUri());
Writer writer = fileObject.openWriter();
javaFile.writeTo(writer);
writer.close();
} catch (IOException x) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, x.toString());
}
}
return false;
}

总结

编写的注解以及process的实现只是做个模板,具体情况视情况而定。

坚持原创技术分享,您的支持将鼓励我继续创作!
区长 WeChat Pay

微信打赏