【JAVA】Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎

2023-12-20 20:12:14

一、介绍

Aviator是一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值。Aviator相比于Groovy、JRuby的笨重,Aviator非常轻量。

#二、原理和特点

  • 高性能:Aviator 的基本过程是将表达式直接翻译成对应的 java 字节码执行,整个过程最多扫两趟(开启执行优先模式,如果是编译优先模式下就一趟),这样就保证了它的性能超越绝大部分解释性的表达式引擎

  • 轻量级:除了依赖 commons-``beanutils 这个库之外(用于做反射)不依赖任何第三方库,因此整体非常轻量级,整个 jar 包大小哪怕发展到现在 5.0 这个大版本,也才 430K

  • 一些比较有特色的特点:

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

#三、Hello World

#1、Java使用

依赖引入

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

案例

public class RunScriptExample {
    public static void main(String[] args) throws IOException {
        // Enable java method invocation by reflection.
        AviatorEvaluator.getInstance()
                .setFunctionMissing(JavaMethodReflectionFunctionMissing.getInstance());
        // You can trry to test every script in examples folder by changing the file name.
        Expression exp = AviatorEvaluator.getInstance().compileScript("/Users/10072656/IdeaProjects/spring-demo/src/main/java/com/example/springdemo/examples/hello.av");

        exp.execute();
    }
}

#2、编译和执行

#2.1、AviatorScript引擎

AviatorScript编译和执行的入口都是AviatorEvaluator类,该类的一个实例就是一个编译和执行的单元,这个单元我们称为一个 AviatorScript 引擎AviatorEvaluator.getInstance() 返回一个全局共享的 AviatorScript 引擎。

#2.2、编译脚本文件

用 compileScript(path) 方法编译一个脚本文件,这个方法对文件路径查找按照下列顺序:

  • path 指定的文件系统绝对或者相对路径
  • user.dir 项目的根目录开始的相对路径
  • classpath 下的绝对和相对路径

找到就尝试读取脚本并动态实时地编译成 JVM 字节码,最终的结果是一个 Expression 对象,每次调用 compileScript(path) 都生成一个新的匿名类和对象,因此如果频繁调用会占满 JVM 的 metaspace,可以通过第二个参数决定是否缓冲:

Expression exp = AviatorEvaluator.getInstance().compileScript("examples/hello.av", true);
exp.execute();
#2.3、编译文本文件

如果我们脚步存储在其他地方,比如数据库、外部文件等,获取后得到的是一个String对象,我们可以使用comiple方法来编译:

Expression compile = AviatorEvaluator.getInstance().compile("println('Hello, AviatorScript!');");
compile.execute();
#2.4、执行

编译产生的 Expression 对象,最终都是调用 execute() 方法执行,得到结果。但是 execute 方法还可以接受一个变量列表组成的 map,来注入执行的上下文,我们来一个例子:

public class RunAcExample {
    public static void main(String[] args) {
        String expression = "a + b > 100";
        Expression compile = AviatorEvaluator.compile(expression);
        Object execute = compile.execute(compile.newEnv("a", 80, "b", 70));
        System.out.println(execute);
    }
}

我们定义了一个表达式,但是这个表达式的参数具体数值没有指定,我们可以在执行的时候指定具体的数值。

#2.5、语法校验
        AviatorEvaluator.validate("1 ++ 2");

#四、基本类型和语法

#1、基本类型及运算

#1.1、整数

整数例如 -99、0、1、2、100……等等,对应的类型是 java 中的 long 类型。AviatorScript 中并没有 byte/short/int 等类型,统一整数类型都为 long,支持的范围也跟 java 语言一样。

let a = 99;
let b = 0xFF;
let c = -99;

println(a + b);
println(a / b);
println(a- b + c);
println(a + b * c);
println(a- (b - c));
println(a/b * b + a % b);
public class Number {
    public static void main(String[] args) throws IOException {
        Expression expression = AviatorEvaluator.getInstance().compileScript("src/main/java/com/example/springdemo/examples/number_demo/number.av");
        Object execute = expression.execute();
        System.out.println(execute);
    }
}

整数相除的结果仍然是整数,比如例子中的 **a/b** 结果就是 0,遵循 java 的整数运算规则。

#1.2、大整数
let a = 10223372036854774807;  ## Literal BigInteger
let b = 1000N;  ## BigInteger
let c = 1000; ## long type

println(a);

println(a + a);

println(a * a);

println(a + b + c);
#1.3、浮点数

数字除了整数之外,AviatorScript 同样支持浮点数,但是仅支持 double 类型,也就是双精度 64 位,符合 IEEE754 规范的浮点数。传入的 java float 也将转换为 double 类型。所有的浮点数都被认为是 double 类型。浮点数的表示形式有两种:

  • 十进制的带小数点的数字,比如 1.34159265 , 0.33333 等等。

  • 科学计数法表示,如 1e-2 , 2E3 等等,大小写字母 e 皆可。

let a = 2;
let err = 1e-15;
let root = a;

while math.abs(a - root * root) &

文章来源:https://blog.csdn.net/wjianwei666/article/details/132324920
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。