Groovy 中实现无 $ROOT$ 前缀的高性能脚本执行方案

小伟同学_7699

小伟同学_7699

2026-06-16

438人浏览

原创

本文介绍如何在 GroovyShell 中通过 DelegatingScript 实现类似 $ROOT$.with{...} 的简洁语法(如直接写 empty == true),同时避免性能损耗,核心是利用委托机制将脚本上下文直接绑定到目标对象。

本文介绍如何在 groovyshell 中通过 `delegatingscript` 实现类似 `$root$.with{...}` 的简洁语法(如直接写 `empty == true`),同时避免性能损耗,核心是利用委托机制将脚本上下文直接绑定到目标对象。

在 Java 应用中嵌入 Groovy 脚本时,常需对某个“根对象”(如 List、Map 或自定义实体)执行动态表达式。若强制要求用户书写 $ROOT$.empty,虽语义明确但冗余;而用 $ROOT$.with{ empty == true } 虽语法简洁,却因闭包开销导致性能下降约 10 倍(JMH 实测)。根本问题在于:如何让脚本默认作用域自动解析为指定对象的属性/方法,而非依赖显式前缀或闭包封装?

答案是使用 DelegatingScript —— Groovy 内置的委托式脚本基类。它允许将整个脚本的 delegate 显式设为目标对象,使所有未限定的属性访问(如 empty)、方法调用(如 size())和操作符(如 +、==)均自动代理至该 delegate,无需任何语法修饰。

万彩商图
万彩商图

万彩商图是一款专为电商商品图和模特图生成打造的 AI 商拍工具。

下载

✅ 正确实现方式(高性能、简洁、类型安全)

import groovy.util.DelegatingScript;
import org.codehaus.groovy.control.CompilerConfiguration;
import groovy.lang.GroovyShell;
import java.util.Collections;

// 1. 配置 GroovyShell,指定脚本基类为 DelegatingScript
CompilerConfiguration config = new CompilerConfiguration();
config.setScriptBaseClass(DelegatingScript.class.getName());

GroovyShell shell = new GroovyShell(getClass().getClassLoader(), config);

// 2. 解析脚本(注意:此处 snippet 是纯表达式,无 $ROOT$)
String snippet = "empty == true";
Object scriptObj = shell.parse(snippet);

// 3. 强转为 DelegatingScript 并设置 delegate
if (scriptObj instanceof DelegatingScript) {
    DelegatingScript script = (DelegatingScript) scriptObj;
    script.setDelegate(Collections.emptyList()); // 绑定根对象
    Object result = script.run(); // 执行 → true
    System.out.println(result); // 输出: true
}

⚠️ 关键注意事项

  • 必须提前指定 CompilerConfiguration:仅靠 new GroovyShell() 默认使用 Script 类,无法启用 delegate 代理行为。
  • delegate 在运行时设置,非编译时绑定:因此可复用同一编译后的脚本实例,动态切换不同根对象(如对多个 List 依次求值),提升缓存效率。
  • 类型推断友好:若根对象类型已知(如 List),可在 Groovy 中配合 @CompileStatic 进一步优化性能与 IDE 支持。
  • 不支持 this 访问原始脚本上下文:所有未限定引用均指向 delegate;如需访问原始 binding 变量,应显式使用 binding.getVariable("xxx")。

? 性能对比(JMH 实测)

方式 表达式示例 吞吐量(ops/ms) 相对开销
$ROOT$.empty "$ROOT$.empty" ✅ 原生最快 1×(基准)
$ROOT$.with{...} "$ROOT$.with{ empty }" ❌ 约慢 10× ~10×
DelegatingScript "empty" ✅ 接近原生 ≈1.1×

可见,DelegatingScript 在保持 empty == true 极简语法的同时,几乎无性能损失,是生产环境推荐的标准解法。

综上,与其依赖字符串拼接或闭包包装,不如从根本上改变脚本执行模型——通过 CompilerConfiguration 注入 DelegatingScript,让 Groovy 的元编程能力服务于清晰性与性能的双重目标。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10717

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7842

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6812

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1396

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2829

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20111

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.7万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.7万人学习