JavaPoet 结合 Java 注解在很多知名的开源库中都应用,例如 Butterknife 和 ARouter.
JavaPoet 是用来生成 .java 文件的,它的使用比较简单,按照官方的示例代码套用就可以了。
Java 的注解,有时间会整理,这里先略过。
我做了一个 Dome 说明它们的应用。
先看一下项目的结构。
整个项目包含三个部分:
- app : 主项目,使用我们的注解
- annotationlib: 注解
- javapoetlib: 使用 javaPoet 生成 .java 代码
下面我们一个个来看
1. 注解
我们先生成一个 java library 生成注解, 这里不能选 android library, 命名为 annotationlib.
它的 build.gradle 文件我们不用修改, 我们看到它是 java-library
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
创建一个名为 MyAnnotation 的接口文件, 它的内容也是非常简单的
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation {
int action() default 0;
}
2. JavaPoet 生成 .java 文件
同样创建一个 java library, 命名为 javapoetlib, 但是它的 build.gradle 文件,我们要修改
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
compile project(':annotationlib')
compile 'com.google.auto.service:auto-service:1.0-rc2'
compile 'com.squareup:javapoet:1.9.0'
}
sourceCompatibility = "1.7"
targetCompatibility = "1.7"
我们添加对刚刚创建的 annotationlib 依赖,同时添加 auto-service 和 javapoet.
我们创建一个 MyProcessor 的文件
@AutoService(Processor.class) // 需要添加
public class MyProcessor extends AbstractProcessor {
private Filer mFiler;
private Elements mElementUtils;
private Messager mMessager;
private static final String PACK_NAME = "com.yxhuang.temp";
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mFiler = processingEnv.getFiler();
mElementUtils = processingEnv.getElementUtils();
mMessager = processingEnv.getMessager();
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported(); // 版本
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(MyAnnotation.class.getCanonicalName()); // 注解的类
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
System.out.print("MyProcessor process");
MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC) // 添加标识符 public static
.returns(void.class) // 返回类型
.addParameter(String[].class, "args") // 方法的参数
.addStatement("$T.out.println($S)", System.class, "Hello World!") // 方法里面的语句声明
.build();
// 构建 HelloWorld 类
TypeSpec hellWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
// 生成 java 文件
JavaFile javaFile = JavaFile.builder(PACK_NAME, hellWorld).build();
try {
javaFile.writeTo(mFiler);
} catch (Exception e){
e.printStackTrace();
}
return true;
}
}
相关的信息,可以看上面代码的注释
- 主要是添加 auto 的注解
@AutoService(Processor.class)
- 版本号
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
- 注解的类型
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(MyAnnotation.class.getCanonicalName()); // 注解的类
}
在 process 方法中使用 JavaPoet 中的方法,生成一个输出 Hello world 的代码,这是一个官方的实例代码,关于 JavaPoet 的使用,可以去 JavaPoet github 主页 去查询。
3. 项目中对注解的使用
在项目中对上面两个 java library 引用
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
annotationProcessor project(':javapoetlib')
implementation project(':annotationlib')
...
}
在 activity 中使用 annoation 注解
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@MyAnnotation(action = 2)
public void test(){
}
}
现在所有的准备工作都做好,我们选择 Make Project 即可,然后我们在 app/build/generated/source/apt/debug 目录下看到生成的 hello world 文件了