news 2026/2/18 4:44:57

Java 动态引擎 Liquor

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 动态引擎 Liquor

Liquor (动态编译后)就是 Java 原生运行,比一般的 JVM 脚本(或表达式)性能高 “20 倍” 左右

Liquor 是一个开源的轻量级 Java 动态编译器

Liquor Java 动态编译器。支持完整的 Java 语法及各版本特性编译特点:

  • 可以指定父类加载器(默认,为当前线程内容类加载器)
  • 可以单个类编译
  • 可以多个类同时编译
  • 可以增量编译
  • 非线程安全。多线程时,要注意锁控制。
  • 编译的性能,可以按“次”计算。尽量多类编译一次。
  • 可以与主项目一起调试

Liquor的核心价值在于业务敏捷性,即用户在界面上的配置(流程、规则、公式、代码)必须实时生效,而传统的 Java 开发模式是强静态编译的,新代码需要重新编译、打包和重启。

Liquor充当了运行时 JIT 编译器和规则引擎。它弥合了 “配置” 与 “高性能 Java 运行时” 之间的鸿沟。它解决了 Java 生态中热更新、高性能、强类型三者难以兼得的根本矛盾。

1. 动态编译即服务 (Dynamic Compilation-as-a-Service)

Liquor 的 DynamicCompiler 模块将编译能力从开发工具链中解放出来,变为一个运行时的服务能力。

  • 实现机制: 低代码平台的前端配置(如拖拽流程、设置数据源映射)经过后端解析器,被转化为标准的 Java 代码片段。Liquor 在运行时调用 Java Compiler API 将这些代码编译成字节码。
  • 技术价值: 平台无需依赖外部的编译环境,也不需要进行耗时的重启。新业务逻辑直接在内存中生成、加载并执行,实现了业务逻辑的零停机热更新。

2. 代码示例:流程节点的动态实现

// 低代码平台解析用户配置,生成一个 Java 类或方法 String customLogicCode = """ import com.platform.utils.DataConverter; import java.util.Map; // 增加 Map 导入,使代码更完整 public class CustomProcessor { public Map<String, Object> process(Map<String, Object> inputData) { if ((double)inputData.get("amount") > 1000) { inputData.put("status", "HighValue"); } // 调用平台内置工具类 inputData.put("convertedKey", DataConverter.hashKey(inputData.get("originalKey"))); return inputData; } } """; // Liquor 运行时编译和加载 DynamicCompiler compiler = new DynamicCompiler(); compiler.addSource("CustomProcessor", customLogicCode).build(); // 实例化并执行 (模拟流程引擎调用) Class<?> clazz = compiler.getClassLoader().loadClass("CustomProcessor"); Object processor = clazz.getDeclaredConstructor().newInstance(); // ... 调用 processor.process(data) ...

2. 代码示例:高性能表达式求值 (Exprs 应用)

在数据校验和计算字段场景中,保证计算速度至关重要:

// 1. 定义一个用于计算的表达式 CodeSpec calculationSpec = new CodeSpec("basePrice * (1 + taxRate) + shippingFee") .parameters( new ParamSpec("basePrice", Double.class), new ParamSpec("taxRate", Double.class), new ParamSpec("shippingFee", Double.class) ); // 2. 首次执行(触发编译并缓存) Map<String, Object> data1 = Map.of("basePrice", 100.0, "taxRate", 0.1, "shippingFee", 5.0); Double total1 = Exprs.eval(calculationSpec, data1); // 首次编译 // 3. 第二次执行(直接命中缓存,极快) Map<String, Object> data2 = Map.of("basePrice", 200.0, "taxRate", 0.1, "shippingFee", 5.0); Double total2 = Exprs.eval(calculationSpec, data2); // 直接执行字节码

三、构建动态扩展点的基石:动态 Bean 与 IoC 集成

1. 动态类加载与 IoC 容器集成 (Dynamic Class Loading & IoC)

Liquor 编译生成的类由其内部的 DynamicClassLoader 负责加载。

  • 实现机制:

平台利用 Liquor 的集成特性(如对 Spring 或 Solon 的支持),将动态编译的类(例如一个带有 @Component 注解的 Service 类)注册到 IoC (Inversion of Control) 容器中。

  • 技术价值:

动态依赖注入: 动态生成的代码可以直接 @Autowired 或 @Inject 平台中已有的服务 Bean。

动态 API 暴露: 动态编译的 Controller 类可以即时映射到 URL 路径,实现 动态 API 接口的发布,为低代码平台提供了灵活的微服务扩展能力。

编译后,从 ClassLoader 获取类。

public class DemoApp { public static void main(String[] args) throws Exception{ //可以复用(可以,不断的增量编译) DynamicCompiler compiler = new DynamicCompiler(); String className = "HelloWorld"; String classCode = "public class HelloWorld { " + " public static void helloWorld() { " + " System.out.println(\"Hello world!\"); " + " } " + "}"; //添加源码(可多个)并 构建 compiler.addSource(className, classCode).build(); //构建后,仍可添加不同类的源码再构建 Class<?> clazz = compiler.getClassLoader().loadClass(className); clazz.getMethod("helloWorld").invoke(null); } }

3、多类编译示例

可以把需要编译的代码收集后,多类编译一次。这样,时间更少。

public class DemoApp { @Test public void test() throws Exception{ DynamicCompiler compiler = new DynamicCompiler(); compiler.addSource("com.demo.UserDo", "package com.demo;\n" + "import java.util.HashMap;\n\n"+ "public class UserDo{\n" + " private String name;\n" + "\n" + " public String getName() {\n" + " return name;\n" + " }\n" + " \n" + " public UserDo(String name) {\n" + " this.name = name;\n" + " }\n" + "}"); compiler.addSource("com.demo.IUserService", "package com.demo;\n" + "public interface IUserService {\n" + " UserDo getUser(String name);\n" + "}"); compiler.addSource("com.demo.UserService", "package com.demo;\n" + "public class UserService implements IUserService {\n" + " @Override\n" + " public UserDo getUser(String name) {\n" + " return new UserDo(name);\n" + " }\n" + "}"); compiler.build(); Class<?> clz = compiler.getClassLoader().loadClass("com.demo.UserService"); Object obj = clz.newInstance(); System.out.println(obj); System.out.println(obj.getClass()); Object objUser = clz.getMethods()[0].invoke(obj, "noear"); System.out.println(objUser); System.out.println(objUser.getClass()); } }

4、类加载器的切换

类加载器 ClassLoader 内部是基于 hash 管理类的,所以相同的类名只能有一个。。。如果我们需要对相同的类名进行编译。可以采用两种方式:

  • 重新实例化动态编译器(DynamicCompiler)
  • 通过切换类加载器(也可以新建类加载器)。应用时,可建立识别体系,识别是重要换新的类加载器?
ClassLoader cl_old = compiler.getClassLoader(); ClassLoader cl_new = compiler.newClassLoader(); compiler.setClassLoader(cl_new); compiler.addSource("..."); compiler.build(); //...用完,可以换回来 //只是示例 compiler.setClassLoader(cl_old);

参考:

源码地址:https://gitee.com/noear/liquor

https://solon.noear.org/article/liquor

具体可参考示例模块:demo_dynamic_compiling_and_debugging_solon

Bilibili 视频演示:《Liquor Java 动态编译神器 - 随心所欲的动态编译与调试》

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/9 0:45:10

23、Linux常见问题及解决指南

Linux常见问题及解决指南 在使用Linux系统的过程中,我们难免会遇到各种各样的问题。本文将为大家介绍一些常见的Linux问题及相应的解决方法,同时还会分享一些获取Linux信息的途径。 一、获取Linux信息的途径 在解决具体问题之前,我们先了解一下可以从哪些地方获取更多关于…

作者头像 李华
网站建设 2026/2/17 7:05:49

基于SpringBoot的健身服务管理系统计算机毕业设计项目源码文档

项目整体介绍基于 SpringBoot 的健身服务管理系统&#xff0c;直击 “健身房会员管理混乱、课程预约低效、私教排课冲突、运营数据无分析” 的核心痛点&#xff0c;依托 SpringBoot 轻量级框架优势与健身行业场景适配能力&#xff0c;构建 “会员管控 课程运营 私教管理 数据…

作者头像 李华
网站建设 2026/2/16 14:58:21

Min浏览器跨平台终极指南:一键安装与最佳配置完整解析

Min浏览器跨平台体验为用户提供了前所未有的灵活性和便捷性。无论你是Windows、macOS还是Linux用户&#xff0c;这款简约快速的浏览器都能完美适配你的系统需求。在前100字的概要中&#xff0c;我们将带你快速了解Min浏览器跨平台的核心优势。 【免费下载链接】min A fast, min…

作者头像 李华
网站建设 2026/2/17 4:59:33

AI如何自动完成LocalDate与Date的相互转换

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个Java工具类&#xff0c;实现java.time.LocalDate与java.util.Date之间的相互转换。要求包含以下方法&#xff1a;1. LocalDate转Date&#xff08;考虑时区&#xff09; 2. …

作者头像 李华
网站建设 2026/2/15 22:05:56

告别手动配置:WSL自动化安装全攻略

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 设计一个自动化脚本工具&#xff0c;能够一键完成WSL的安装和配置。工具应包含以下功能&#xff1a;1. 自动启用Windows功能&#xff08;如Hyper-V、虚拟机平台&#xff09;&#x…

作者头像 李华
网站建设 2026/2/16 23:40:53

AI音频分离终极指南:从技术原理到实战应用全解析

AI音频分离终极指南&#xff1a;从技术原理到实战应用全解析 【免费下载链接】ultimatevocalremovergui 使用深度神经网络的声音消除器的图形用户界面。 项目地址: https://gitcode.com/GitHub_Trending/ul/ultimatevocalremovergui 在数字音乐制作和音频处理领域&#…

作者头像 李华