Aviator 轻量高性能 Java 表达式引擎

Aviator简介

Aviator 的基本过程是将表达式直接翻译成对应的 java 字节码执行,整个过程最多扫两趟(开启执行优先模式,如果是编译优先模式下就一趟),这样就保证了它的性能超越绝大部分解释性的表达式引擎,测试也证明如此;其次,除了依赖 commons-beanutils 这个库之外(用于做反射)不依赖任何第三方库,因此整体非常轻量级,整个 jar 包大小哪怕发展到现在 5.0 这个大版本,也才 430K。同时, Aviator 内置的函数库非常“节制”,除了必须的字符串处理、数学函数和集合处理之外,类似文件 IO、网络等等你都是没法使用的,这样能保证运行期的安全,如果你需要这些高阶能力,可以通过开放的自定义函数来接入。
因此总结它的特点是:

  • 高性能
  • 轻量级
  • 一些比较有特色的特点:
    1. 支持运算符重载
    2. 原生支持大整数和 BigDecimal 类型及运算,并且通过运算符重载和一般数字类型保持一致的运算方式。
    3. 原生支持正则表达式类型及匹配运算符 =~
    4. 类 clojure 的 seq 库及 lambda 支持,可以灵活地处理各种集合
  • 开放能力:包括自定义函数接入以及各种定制选项

官方文档:https://www.yuque.com/boyan-avfmj/aviatorscript/guhmrc

Aviator的特性

  • 支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、正则匹配操作符(=~)、三元表达式?:,并且支持操作符的优先级和括号强制优先级,具体请看后面的操作符列表。
  • 支持函数调用和自定义函数。
  • 支持正则表达式匹配,类似Ruby、Perl的匹配语法,并且支持类Ruby的$digit指向匹配分组。
  • 自动类型转换,当执行操作的时候,会自动判断操作数类型并做相应转换,无法转换即抛异常。
  • 支持传入变量,支持类似a.b.c的嵌套变量访问。
  • 性能优秀。

Aviator的限制

  • 没有if else、do while等语句,没有赋值语句,没有位运算符;
  • 仅支持逻辑表达式、算术表达式、三元表达式和正则匹配。

最新jar包

    <dependency>
      <groupId>com.googlecode.aviator</groupId>
      <artifactId>aviator</artifactId>
      <version>5.3.0</version>
    </dependency>

Aviator编译和执行

AviatorScript 引擎

AviatorScript 编译和执行的入口是AviatorEvaluatorInstance类,该类的一个实例就是一个编译和执行的单元,这个单元我们称为一个 AviatorScript 引擎,你可以多个引擎,每个引擎可以设置不同的编译和运行选项。

编译脚本文件

将表达式编译成JVM字节码,最终的结果对象为Expression,所有的表达式最终编译的结果都是一个Expression对象,他经过:

  • Lexer文法分析;
  • Parser语法解析;
  • 第一趟优化:常量折叠、常量池等简单优化;
  • 第二趟生成JVM字节码,并最终动态生成一个匿名的Class;
  • 实例化Class得到最终的Expression。

每次调用 compileScript(path) 都生成一个新的匿名类和对象,因此如果频繁调用会占满 JVM 的 metaspace,可能导致 full gc 或者 OOM(关于这一点我们将在最佳实践里更详细的解释),因此还有一个方法 compileScript(path, cached) 可以通过第二个布尔值参数决定是否缓存该编译结果。

执行

编译产生的 Expression 对象,最终都是调用 execute() 方法执行,得到结果。但是 execute 方法还可以接受一个变量列表组成的 map,使得表达式更加灵活。

使用示例

  @Test
    public void testExpressCompile(){
        String expression = "if(a > b){p('a大于b');}else{p('a小于或等于b');return a+b;} ";
        Map<String,Object> env = new HashMap<>(16);
        env.put("a", 100);
        env.put("b", 1000);
        AviatorEvaluatorInstance instance = AviatorEvaluator.getInstance();
        Object execute = instance.execute(expression, env);
        System.out.println(execute);
    }
   	/**
     * 打印结果如下:
     * a小于或等于b
     * 1100
     * */

点击跳转查看官方文档

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值