什么是JavaPoet,就是APT+javaPoet =超级利刃
javaPoet是square公司推出的开源代码生成框架,提供api生成.java 源文件,这个框架功能非常实用,也是我们习惯的面向对象oop思想 可以很方便的使用它根据注解生成代码 通过这种自动化生成代码的方式 可以让我们更加简洁优雅的方式来替代复杂的工作
它的github地址 javaPoet
它的官网有很多例子 可以跟着写
javaPoet和前一篇博客生成文件的顺序不一样,javaPoet是倒着来的
javaPoet常用的8个类
这些写多了就记住了
javaPoet字符串格式化规则
新建一个项目JavaPoetTest 二个library 一个是annotation 一个是compiler
跟上篇博客配置是一样的,这就不再说了,直接看下process()方法,看下javaPoet github地址 它有demo,先把demo练习几篇就会了
比如要创建这个类
package com.example.helloworld;
public final class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, JavaPoet!");
}
}
官网给的代码
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if(set.isEmpty()){
return false;
}
messager.printMessage(Diagnostic.Kind.NOTE, "1111111");
MethodSpec main = MethodSpec.methodBuilder("main")//main是方法名
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)//添加方法修饰符
.returns(void.class)//方法返回值
.addParameter(String[].class, "args")//行参类型和行参变量名字
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")//这是方法里面的内容 $T $s表示类和字符串 跟String.format("%d几岁",%d)跟String的格式一样
.build();
//这是添加类信息
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")//添加类名字
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)//类修饰符
.addMethod(main)//添加类方法
.build();
//这是把该类放到对应的包中
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
messager.printMessage(Diagnostic.Kind.NOTE, "22222");
//写到控制台 方便查看
try {
javaFile.writeTo(System.out);
} catch (IOException e) {
e.printStackTrace();
}
try {
//这个必须得调用 不然生不了文件
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
然后make module app下就行了,看下build控制台
再看下app. module下的build目录下查看生成的文件
现在再来写我们自己写的ARouter注解处理器要生成的文件,如下
public class MainActivity$$ARouter {
public static Class findTargetClass(String path) {
return path.equals("/app/MainActivity") ? MainActivity.class : null;
}
}
process()方法中的代码
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if(set.isEmpty()){
return false;
}
// 获取所有带ARouter注解的 类节点
Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
// 遍历所有类节点
for (Element element : elements) {
// 通过类节点获取包节点(全路径:com.netease.xxx)
String packageName = elementUtils.getPackageOf(element).getQualifiedName().toString();
messager.printMessage(Diagnostic.Kind.NOTE, "packageName="+packageName);
// 获取简单类名
String className = element.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE, "className="+className);
// messager.printMessage(Diagnostic.Kind.NOTE, "被注解的类有:" + className);
// 最终想生成的类文件名
String finalClassName = className + "$$ARouter";
// 高级写法,javapoet构建工具,参考(https://github.com/JakeWharton/butterknife)
try {
// 获取类之上@ARouter注解的path值
ARouter aRouter = element.getAnnotation(ARouter.class);
// 构建方法体
MethodSpec method = MethodSpec.methodBuilder("findTargetClass") // 方法名
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(Class.class) // 返回值Class<?>
.addParameter(String.class, "path") // 参数(String path)
// 方法内容拼接:
// return path.equals("/app/MainActivity") ? MainActivity.class : null
.addStatement("return path.equals($S) ? $T.class : null",
aRouter.path(), ClassName.get((TypeElement) element))
.build(); // 构建
// 构建类
TypeSpec type = TypeSpec.classBuilder(finalClassName)
.addModifiers(Modifier.PUBLIC) //, Modifier.FINAL)
.addMethod(method) // 添加方法体
.build(); // 构建
// 在指定的包名下,生成Java类文件
JavaFile javaFile = JavaFile.builder(packageName, type)
.build();
javaFile.writeTo(System.out);
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
ok,