前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Groovy】编译时元编程 ( ASTTransformation#visit 方法中访问 Groovy 类、方法、字段、属性 | 完整代码示例及进行编译时处理的编译过程 )

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

作者头像
韩曙亮
发布2023-03-30 11:06:31
8300
发布2023-03-30 11:06:31
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

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


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

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

代码语言:javascript
复制
source.AST.classes

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

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

代码语言:javascript
复制
source.AST.classes.each {
	it 
}

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

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

代码示例 :

代码语言:javascript
复制
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 源单元 , 可以通过该对象拿到源文件
     */
    @Override
    void visit(ASTNode[] nodes, SourceUnit source) {
        println nodes
        println source
        println source.AST
        println source.source.reader.text

        // 获取 Groovy.groovy 脚本中的类集合 , 并进行遍历
        // 在 ModuleNode 中的类节点封装在了如下成员中
        // List<ClassNode> classes = new LinkedList<ClassNode>();
        source.AST.classes.each {
            it.visitContents(new GroovyClassVisitor() {
                @Override
                void visitClass(ClassNode node) {
                    // 分析类的方法
                    println "visitClass ${node.name}"
                }

                @Override
                void visitConstructor(ConstructorNode node) {
                    // 分析类构造方法
                    println "visitConstructor ${node.name}"
                }

                @Override
                void visitMethod(MethodNode node) {
                    // 分析普通方法
                    println "visitMethod ${node.name}"
                }

                @Override
                void visitField(FieldNode node) {
                    // 分析字段
                    println "visitField ${node.name}"
                }

                @Override
                void visitProperty(PropertyNode node) {
                    // 分析属性
                    println "visitProperty ${node.name}"
                }
            })
        }
    }
}

编译时输出结果 :

代码语言:javascript
复制
visitConstructor <init>
visitConstructor <init>
visitMethod main
visitMethod run
visitProperty name
visitField name
visitMethod hello

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


1、Groovy 脚本 Groovy.groovy

代码语言:javascript
复制
class Student{
    def name
    def hello(){
        println "hello"
    }
}

def student = new Student()
在这里插入图片描述
在这里插入图片描述

2、ASTTransformation 接口实现 MyASTTransformation.groovy

代码语言:javascript
复制
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 源单元 , 可以通过该对象拿到源文件
     */
    @Override
    void visit(ASTNode[] nodes, SourceUnit source) {
        println nodes
        println source
        println source.AST
        println source.source.reader.text

        // 获取 Groovy.groovy 脚本中的类集合 , 并进行遍历
        // 在 ModuleNode 中的类节点封装在了如下成员中
        // List<ClassNode> classes = new LinkedList<ClassNode>();
        source.AST.classes.each {
            it.visitContents(new GroovyClassVisitor() {
                @Override
                void visitClass(ClassNode node) {
                    // 分析类的方法
                    println "visitClass ${node.name}"
                }

                @Override
                void visitConstructor(ConstructorNode node) {
                    // 分析类构造方法
                    println "visitConstructor ${node.name}"
                }

                @Override
                void visitMethod(MethodNode node) {
                    // 分析普通方法
                    println "visitMethod ${node.name}"
                }

                @Override
                void visitField(FieldNode node) {
                    // 分析字段
                    println "visitField ${node.name}"
                }

                @Override
                void 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 实现类的全类名 :

代码语言:javascript
复制
MyASTTransformation
在这里插入图片描述
在这里插入图片描述

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

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

代码语言:javascript
复制
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 目录下 ,

代码语言:javascript
复制
groovyc -d classes MyASTTransformation.groovy

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

代码语言:javascript
复制
jar -cf test.jar -C classes . -C resources .

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

代码语言:javascript
复制
groovy -classpath test.jar Groovy.groovy

执行结果为 :

代码语言:javascript
复制
[org.codehaus.groovy.ast.ModuleNode@2b175c00]
org.codehaus.groovy.control.SourceUnit@3eb81efb
org.codehaus.groovy.ast.ModuleNode@2b175c00
class Student{
    def name
    def hello(){
        println "hello"
    }
}

def student = new Student()
visitConstructor <init>
visitConstructor <init>
visitMethod main
visitMethod run
visitProperty name
visitField name
visitMethod hello
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-02-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、ASTTransformation#visit 方法中访问 Groovy 类、方法、字段、属性
  • 二、完整代码示例及进行编译时处理的编译过程
    • 1、Groovy 脚本 Groovy.groovy
      • 2、ASTTransformation 接口实现 MyASTTransformation.groovy
        • 3、配置 ASTTransformation
          • 3、使用命令行进行编译时处理
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档