欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

【Groovy】编译时元编程 ( ASTTransformation#visit 方法中访问 Groovy 类、方法、字段、属性 | 完整代码示例及进行编译时处理的编译过程 )

发布时间:2025/6/17 编程问答 45 豆豆

文章目录

  • 一、ASTTransformation#visit 方法中访问 Groovy 类、方法、字段、属性
  • 二、完整代码示例及进行编译时处理的编译过程
    • 1、Groovy 脚本 Groovy.groovy
    • 2、ASTTransformation 接口实现 MyASTTransformation.groovy
    • 3、配置 ASTTransformation
    • 3、使用命令行进行编译时处理





一、ASTTransformation#visit 方法中访问 Groovy 类、方法、字段、属性



在 ASTTransformation#visit 方法中 , 使用 source.AST 可以获取 Groovy 脚本的 AST 语法树节点 , 该节点是 ModuleNode 类型的 , 在一个 Groovy 脚本中可以定义多个 Class 类 , 其对应的 Class 语法树节点封装在了 ModuleNode 类的 List<ClassNode> classes = new LinkedList<ClassNode>(); 成员中 ;


因此 , 在 ASTTransformation#visit 方法中 , 可以使用

source.AST.classes

获取 Groovy 脚本中定义的所有 Groovy 类 ;


使用 each 方法遍历上述 Class 类节点集合 List<ClassNode> classes , 在闭包中 , 使用 it 获取正在遍历的 ClassNode 类型的集合元素 ;

source.AST.classes.each {it }

遍历时 , 执行 ClassNode 对象的 visitContents 方法 , 传入 GroovyClassVisitor 对象 , 用于访问 Groovy 的每个类 ;

GroovyClassVisitor 对象中 , 提供了访问 类 、成员字段 、成员方法 、属性 、 构造函数的回调方法 ;


代码示例 :

import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.ConstructorNode import org.codehaus.groovy.ast.FieldNode import org.codehaus.groovy.ast.GroovyClassVisitor import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.PropertyNode import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.ASTTransformation import org.codehaus.groovy.transform.GroovyASTTransformation@GroovyASTTransformation class MyASTTransformation implements ASTTransformation {/*** 编译时处理方法* @param nodes AST 抽象语法树节点 , 是 ASTNode 数组类型* @param source 源单元 , 可以通过该对象拿到源文件*/@Overridevoid visit(ASTNode[] nodes, SourceUnit source) {println nodesprintln sourceprintln source.ASTprintln source.source.reader.text// 获取 Groovy.groovy 脚本中的类集合 , 并进行遍历// 在 ModuleNode 中的类节点封装在了如下成员中// List<ClassNode> classes = new LinkedList<ClassNode>();source.AST.classes.each {it.visitContents(new GroovyClassVisitor() {@Overridevoid visitClass(ClassNode node) {// 分析类的方法println "visitClass ${node.name}"}@Overridevoid visitConstructor(ConstructorNode node) {// 分析类构造方法println "visitConstructor ${node.name}"}@Overridevoid visitMethod(MethodNode node) {// 分析普通方法println "visitMethod ${node.name}"}@Overridevoid visitField(FieldNode node) {// 分析字段println "visitField ${node.name}"}@Overridevoid visitProperty(PropertyNode node) {// 分析属性println "visitProperty ${node.name}"}})}} }

编译时输出结果 :

visitConstructor <init> visitConstructor <init> visitMethod main visitMethod run visitProperty name visitField name visitMethod hello



二、完整代码示例及进行编译时处理的编译过程




1、Groovy 脚本 Groovy.groovy


class Student{def namedef hello(){println "hello"} }def student = new Student()


2、ASTTransformation 接口实现 MyASTTransformation.groovy


import org.codehaus.groovy.ast.ASTNode import org.codehaus.groovy.ast.ClassNode import org.codehaus.groovy.ast.ConstructorNode import org.codehaus.groovy.ast.FieldNode import org.codehaus.groovy.ast.GroovyClassVisitor import org.codehaus.groovy.ast.MethodNode import org.codehaus.groovy.ast.PropertyNode import org.codehaus.groovy.control.SourceUnit import org.codehaus.groovy.transform.ASTTransformation import org.codehaus.groovy.transform.GroovyASTTransformation@GroovyASTTransformation class MyASTTransformation implements ASTTransformation {/*** 编译时处理方法* @param nodes AST 抽象语法树节点 , 是 ASTNode 数组类型* @param source 源单元 , 可以通过该对象拿到源文件*/@Overridevoid visit(ASTNode[] nodes, SourceUnit source) {println nodesprintln sourceprintln source.ASTprintln source.source.reader.text// 获取 Groovy.groovy 脚本中的类集合 , 并进行遍历// 在 ModuleNode 中的类节点封装在了如下成员中// List<ClassNode> classes = new LinkedList<ClassNode>();source.AST.classes.each {it.visitContents(new GroovyClassVisitor() {@Overridevoid visitClass(ClassNode node) {// 分析类的方法println "visitClass ${node.name}"}@Overridevoid visitConstructor(ConstructorNode node) {// 分析类构造方法println "visitConstructor ${node.name}"}@Overridevoid visitMethod(MethodNode node) {// 分析普通方法println "visitMethod ${node.name}"}@Overridevoid visitField(FieldNode node) {// 分析字段println "visitField ${node.name}"}@Overridevoid visitProperty(PropertyNode node) {// 分析属性println "visitProperty ${node.name}"}})}} }


3、配置 ASTTransformation


创建 Y:\002_WorkSpace\003_IDEA\Groovy_Demo2\src\main\groovy\resources\META-INF\services\org.codehaus.groovy.transform.ASTTransformation 目录层级及文件 , 在文件中配置 ASTTransformation 实现类的全类名 :

MyASTTransformation


3、使用命令行进行编译时处理


首先 , 进入 Y:\002_WorkSpace\003_IDEA\Groovy_Demo2\src\main\groovy 目录 ,

cd Y:\002_WorkSpace\003_IDEA\Groovy_Demo2\src\main\groovy

然后 , 编译 编译时处理类 MyASTTransformation.groovy , 将编译后的字节码文件 MyASTTransformation.class 保存到 Y:\002_WorkSpace\003_IDEA\Groovy_Demo2\src\main\groovy\classes 目录下 ,

groovyc -d classes MyASTTransformation.groovy

再后 , 打包上述编译好的字节码文件 , 存放在 Y:\002_WorkSpace\003_IDEA\Groovy_Demo2\src\main\groovy\test.jar 路径 ;

jar -cf test.jar -C classes . -C resources .

最后 , 依赖 test.jar 执行 Groovy.groovy 脚本

groovy -classpath test.jar Groovy.groovy

执行结果为 :

[org.codehaus.groovy.ast.ModuleNode@2b175c00] org.codehaus.groovy.control.SourceUnit@3eb81efb org.codehaus.groovy.ast.ModuleNode@2b175c00 class Student{def namedef hello(){println "hello"} }def student = new Student() visitConstructor <init> visitConstructor <init> visitMethod main visitMethod run visitProperty name visitField name visitMethod hello

总结

以上是生活随笔为你收集整理的【Groovy】编译时元编程 ( ASTTransformation#visit 方法中访问 Groovy 类、方法、字段、属性 | 完整代码示例及进行编译时处理的编译过程 )的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。