Skip to content

完整选项列表说明

dennis zhuang edited this page May 26, 2019 · 11 revisions

Options支持一些功能的自定义选项,详解如下。

OPTIMIZE_LEVEL

优化级别,更精确地说是运行的优化倾向,可以是:

  • AviatorEvaluator.EVAL,默认值,以运行时的性能优先,编译会花费更多时间做优化,目前会做一些常量折叠、公共变量提取的优化。适合长期运行的表达式。
  • AviatorEvaluator.COMPILE,以编译的性能优先,不会做任何编译优化,牺牲一定的运行性能,适合需要频繁编译表达式的场景。

MATH_CONTEXT

Decimal 数字类型的运算精度,默认是 java.util.MathContext.DECIMAL128

ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL

是否将所有浮点数解析为 Decimal 类型,适合需要高精度运算的场景,并且不想为每个浮点数字指定 M 后缀(表示 Decimal 类型)。默认为 false 不开启。

TRACE_EVAL

是否跟踪运行,打开后将在控制台打印整个表达式的求值过程。请勿在生产环境打开,将极大地降低性能。默认为 false 关闭。

PUT_CAPTURING_GROUPS_INTO_ENV

表示正则匹配的时候,是否将捕获的分组放入 env 环境中,例如

email=~/([\\w0-8]+)@\\w+[\\.\\w+]+/ ? $1:'unknow'

将 email 变量中的用户名部分(@ 符号之前)匹配出来,并放到 $1变量中,如果关闭 PUT_CAPTURING_GROUPS_INTO_ENV(设置为 false),将不会将捕获的分组放入 env,也就无法获取到匹配的分组。默认为 true 开启。

ENABLE_PROPERTY_SYNTAX_SUGAR

是否启用变量访问的语法糖,默认情况下 Aviator 会通过 commons-beantuils 反射访问类似 a.b.c 这样的嵌套 JavaBean 变量,或者 #list.[0].name 这样的数组(链表)中的元素。但是部分用户可能想关闭这个行为,强制都从 env 中获取这些变量值,那么就可以将该选项关闭,也就是设置为 false。默认为 true 开启。

NIL_WHEN_PROPERTY_NOT_FOUND

在启用变量访问糖的情况下,如果反射调用失败,默认的行为将抛出运行时异常,而不是返回 null。可以通过本选项改变这个行为,启用的情况下(也就是设置为 true),将不抛出异常,而是返回 null。 默认为 false 关闭。

USE_USER_ENV_AS_TOP_ENV_DIRECTLY

从 4.0 开始,为了支持 lambda, aviator 引入了变量作用域 scope 的概念,本来的默认行为是不再修改用户传入的 env 对象,但是后面看到比较多的用户依赖这个行为,因此提供了这个新选项 USE_USER_ENV_AS_TOP_ENV_DIRECTLY,当为 true 的时候就会将用户传入的 env 作为最顶层的作用域 scope 来使用,并且默认为 true 启用。如果你不需要 aviator 产生副作用污染你传入的 env,这个选项更推荐设置为 false

DISABLE_ASSIGNMENT

从 4.1.0 开始, aviator 支持赋值,但是在一些场景下可能因为安全的原因,比如你有一个校验函数 validate(x),如果允许赋值,用户可以覆盖这个函数来绕过校验:

validate = lambda(x) -> true end ;  validate(x)

如果表达式是用户传入不可控制,建议关闭赋值功能,将 Options.DISABLE_ASSIGNMENT 设置为 true 即可,默认不关闭。

ALWAYS_PARSE_INTEGRAL_NUMBER_INTO_DECIMAL

是否将整型数字都解析为 BigDecimal,默认为 false,也就是不启用。在所有数字都是需要高精度计算的场景,启用该选项可以减少一些类型转换。

CAPTURE_FUNCTION_ARGS

是否捕获函数调用点的参数列表,如果启用,那么类似 func 这样的自定义函数:

func(a, b, c, 100+2)

这样的表达式,就可以在 func 内得到调用的参数列表,

    @Override
    public AviatorObject call(final Map<String, Object> env, final AviatorObject arg1,
        final AviatorObject arg2, final AviatorObject arg3, final AviatorObject arg4) {
      List<FunctionArgument> args = FunctionUtils.getFunctionArguments(env);
      ......
    } 

得到的 args 就是参数列表:

[FunctionArgument, index=0, expression="a"]
[FunctionArgument, index=1, expression="b"]
[FunctionArgument, index=2, expression="c"]
[FunctionArgument, index=3, expression="100+2"]

在 lambda 中也可以捕获,捕获的调用参数列表存放在 __args__ 变量:

 List<FunctionArgument> args = (List<FunctionArgument>) AviatorEvaluator
          .execute("f = lambda(a,bc, d) -> __args__ end; f(1,2,100+2)");

      assertEquals(3, args.size());

      System.out.println(args);

      assertEquals(0, args.get(0).getIndex());
      assertEquals("1", args.get(0).getExpression());
      assertEquals(1, args.get(1).getIndex());
      assertEquals("2", args.get(1).getExpression());
      assertEquals(2, args.get(2).getIndex());
      assertEquals("100+2", args.get(2).getExpression());

利用这一特性,你可以在运行时对调用的参数做参数校验或者分支派发,以及对于函数调用过程做优化,例如对针对参数做结果缓存等等。

Clone this wiki locally