AST简介
AST(Abstract syntax tree)即为“抽象语法树”,是编辑器对代码的第一步加工之后的结果,是一个树形式表示的源代码。源代码的每个元素映射到一个节点或子树。
Java的编译过程可以分成三个阶段:
image
所有源文件会被解析成语法树。
调用注解处理器。如果注解处理器产生了新的源文件,新文件也要进行编译。
最后,语法树会被分析并转化成类文件。
例如:下面一段java代的抽象语法树大概长这样:
AST
编辑器对代码处理的流程大概是:
JavaTXT->词语法分析-> 生成AST ->语义分析 -> 编译字节码
操作AST时机
通过操作AST,可以达到修改源代码的功能,相比AOP三剑客,他的时机更为提前:
操作AST
什么是 AST 转换?
AST 转换 是在编译过程中用来修改抽象语法树结构的代码的名称。修改 AST,通过在将其转换为字节码之前增加附加节点,是更好的生成代码的方法。
之前我们了解到APT的三个弱点:
1、预留入口不编译会报红,正常运行就可以
2、反射获得新的类效率又太差
3、无法实现定点插桩,只能生成新的类
AST则很好的解决了上面的问题。
如何操作AST?
1、直接使用Javac语法生成AST:
/* final int PRIME = 31; */ {
if (!fields.isEmpty() || callSuper) {
statements.append(maker.VarDef(maker.Modifiers(Flags.FINAL),
primeName, maker.TypeIdent(Javac.getCTCint(TypeTags.class, "INT")),
maker.Literal(31)));
}
}
在javac.tree的JCTree里面,几乎可以看到所有常用语法的关键字:
比如JCImport,JCClassDecl、JCIf、JCBreak、JCReturn、JCThrow
、JCDoWhileLoop、JCTry、JCCatch、JCAnnotation等,你可以直接用这些对象的操作组合成你想要的源码,类似于javapoet的组装模式。
2、借助工具库,更加简单的操作AST
Rewrite、JavaParser等开源工具可以帮助你更简单的操作AST
3、扩展Lombok自定义注解处理器(自行了解)
AOP之AST:
AOP定位插桩,相比重量级的AspectJ,ASM、Javassisit,修改AST可以做更加轻量级的代码插桩实现方案:</