前言
内容摘要
- 注解处理器功能
- JavaPoet 创建类
步骤
1.注解库和注解类
- 新建 java Library 作为注解库, 名为"libmyannotation"
- build.gradle 配置:
// [1] 引入 java-library 插件
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "7"
targetCompatibility = "7"
- 新建注解类 MethodAnnotation:
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface MethodAnnotation {
}
2. 注解处理库
- 再新建 Java Library 作为注解处理库,名为"libmy",此处必须选择 Java Library, 否则有些类如 AbstractProcessor 引不进来
- 配置 build.gradle:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//[1] 自动注册注解处理器, 跟 @AutoService 有关
implementation 'com.google.auto.service:auto-service:1.0-rc4'
// [2] javapoet代码生成框架来生成代码
implementation 'com.squareup:javapoet:1.11.1'
//[3] 依赖自定义注解库
implementation project(':libmyannotation')
//[4] 自动注册注解处理器的处理,会在当前模块的 build 文件夹下生成 /META-INF/services/javax.annotation.processing.Processor
annotationProcessor "com.google.auto.service:auto-service:1.0-rc4"
}
sourceCompatibility = "7"
targetCompatibility = "7"
- 注解处理器类 AbstractProcessor
//[1] AutoService 注解,指定注册服务
@AutoService(Processor.class)
public class MyClass extends AbstractProcessor {
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
// javac Filer
filer = processingEnvironment.getFiler();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
// 支持的注解
Set<String> sets = new HashSet<>();
sets.add(MethodAnnotation.class.getCanonicalName());
return sets;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
System.out.println("这是注解 process" + set + "," + roundEnvironment);
//这个方法会调用三次
//1. [com.xh.libmyannotation.MethodAnnotation],[errorRaised=false, rootElements=[com.xh.testannotationprocess.TestClass, ...], processingOver=false]
//2. [],[errorRaised=false, rootElements=[com.example.HelloWorld], processingOver=false]
//3. [],[errorRaised=false, rootElements=[], processingOver=true]
buildCustomClass();
return true;
}
/**
* 构建类
*/
private void buildCustomClass() {
//创建 main 方法
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 World from JavaPoet!")
.build();
//创建类
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
try {
JavaFile javaFile = JavaFile.builder("com.example", helloWorld)
.addFileComment("This codes are generated automatically. Do not modify!")
.build();
System.out.println("path:" + filer);
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 执行模块的 clean build 命令,可以在build 文件夹下生成 /META-INF/services/javax.annotation.processing.Processor
3. app 模块进行测试
注意:Java 写的注解只能用在 Java 类上。
- 配置 build.gradle
dependencies {
// 依赖注解库
implementation project(':libmyannotation')
//依赖注解处理器库
annotationProcessor project(':libmy')
}
- 新建测试类 Test2Class,书写方法注解,这个注解作为注解处理器生效的触发点
public class Test2Class {
@MethodAnnotation
public void method1(){
}
}
- 执行 clean build 命令,可以在 /build/generated/source/apt/debug/包名/ 下找到自动生成的 HelloWorld 类
// This codes are generated automatically. Do not modify!
package com.example;
import java.lang.String;
import java.lang.System;
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World from JavaPoet!");
}
}