您现在的位置是:首页 >学无止境 >规则引擎架构-基于aviator网站首页学无止境
规则引擎架构-基于aviator
简介规则引擎架构-基于aviator
aviator使用场景
github地址:aviator
Aviator的特性
- 支持大部分运算操作符,包括算术操作符、关系运算符、逻辑操作符、正则匹配操作符(=~)、三元表达式?: ,并且支持操作符的优先级和括号强制优先级,具体请看后面的操作符列表。
- 支持函数调用和自定义函数
- 支持正则表达式匹配,类似Ruby、Perl的匹配语法,并且支持类Ruby的$digit指向匹配分组。
- 自动类型转换,当执行操作的时候,会自动判断操作数类型并做相应转换,无法转换即抛异常。
- 支持传入变量,支持类似a.b.c的嵌套变量访问。
- 性能优秀
Aviator的限制:
- 没有if else、do while等语句,没有赋值语句,仅支持逻辑表达式、算术表达式、三元表达式和正则匹配。
- 没有位运算符
ASM 字节码操控框架
asm实现:直接修改或生成.class
例子代码
package com.googlecode.aviator;
import com.googlecode.aviator.asm.ClassWriter;
import com.googlecode.aviator.asm.MethodVisitor;
import com.googlecode.aviator.asm.Opcodes;
/**
* @author dingqi on 2023/5/29
* @since 1.0.0
*/
public class TestAsm extends ClassLoader{
/**
* 生成一个Class类
* public class User {
*
* public static void main(String[] args) {
* System.out.println("Hello World");
* }
*
* public int add(int a, int b){
* return a + b;
* }
* }
*/
public static byte[] generateClazz() {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
cw.visit(
Opcodes.V1_7,
Opcodes.ACC_PUBLIC,
"com/googlecode/aviator/User",
null,
"java/lang/Object",
null
);
MethodVisitor mv = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"<init>",
"()V",
null,
null
);
// 开始访问方法code
mv.visitCode();
// 局部变量进栈
mv.visitVarInsn(Opcodes.ALOAD, 0);
// 执行特殊实例方法(构造方法)
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
// 方法返回
mv.visitInsn(Opcodes.RETURN);
// 最大栈大小值、最大方法本地参数值
mv.visitMaxs(1, 1);
// 方法结束
mv.visitEnd();
mv = cw.visitMethod(
Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC,
"main",
"(Ljava/lang/String;)V",
null,
null
);
// 开始访问方法code
mv.visitCode();
// 访问static类字段out,参数类型Ljava/io/PrintStream;
mv.visitFieldInsn(
Opcodes.GETSTATIC,
"java/lang/System",
"out",
"Ljava/io/PrintStream;"
);
// 常量加载进栈
mv.visitLdcInsn("Hello World");
// 调用对象的实例方法println,方法参数String数组(Ljava/lang/String;)V
mv.visitMethodInsn(
Opcodes.INVOKEVIRTUAL,
"java/io/PrintStream",
"println",
"(Ljava/lang/String;)V"
);
// 方法返回
mv.visitInsn(Opcodes.RETURN);
// 最大栈大小值、最大方法内本地参数值
mv.visitMaxs(2, 1);
// 方法结束
mv.visitEnd();
// 再添加方法
mv = cw.visitMethod(
Opcodes.ACC_PUBLIC,
"add",
"(II)I",
null,
null
);
// 入参
mv.visitVarInsn(Opcodes.ILOAD,1);
mv.visitVarInsn(Opcodes.ILOAD,2);
mv.visitInsn(Opcodes.IADD); //2个int类型相加
//返回int 类型
mv.visitInsn(Opcodes.IRETURN);
// 设置操作数栈的深度和局部变量的大小:2个数计算,加上this 总共3个变量
mv.visitMaxs(2, 3);
mv.visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
public static void main(String[] args) throws Exception {
TestAsm testAsm = new TestAsm();
byte[] code = TestAsm.generateClazz();
String className = "com.googlecode.aviator.User";
Class<?> clazz = testAsm.defineClass(className, code, 0, code.length);
clazz.getMethods()[0].invoke(null, new Object[]{null});
Object o = clazz.newInstance();
Integer ans = (Integer)clazz.getMethods()[1].invoke(o, 1, 2);
System.out.println("add ans:" + ans);
ans = (Integer)clazz.getMethods()[1].invoke(o, 1, 3);
System.out.println("add ans:" + ans);
}
}
/** 输出
Hello World
add ans:3
add ans:4
*/
aviator 表达式例子
public class AviatorEvaluatorInstanceUnitTest {
protected AviatorEvaluatorInstance instance;
@Before
public void setup() {
this.instance = AviatorEvaluator.newInstance();
}
@Test
public void testExec() {
String exp1 = "b-c+a";
assertEquals(8, this.instance.exec(exp1, 6, 2, 4));
}
}
debug
新生成了一个类Script_1685399425946_58
:
执行execute0方法,参数:com.googlecode.aviator.utils.Env
然后执行成功,得到结果
debug可以看到生成的类确实有方法:public final java.lang.Object Script_1685400413476_58.execute0(com.googlecode.aviator.utils.Env)
表达式类生成过程
依据
String exp1 = "b-c+a";
assertEquals(8, this.instance.exec(exp1, 6, 2, 4));
解析完变量后的asm生成逻辑:
private void callASM(final Map<String, VariableMeta/* metadata */> variables,
final Map<String, Integer/* counter */> methods, final Set<Token<?>> constants) {
this.codeGen.initConstants(constants);
this.codeGen.initVariables(variables);
this.codeGen.initMethods(methods);
this.codeGen.setLambdaBootstraps(this.lambdaBootstraps);
this.codeGen.start();
生成execute0
方法
@Override
public void start() {
makeConstructor();
startVisitMethodCode();
}
private void startVisitMethodCode() {
this.mv = this.classWriter.visitMethod(ACC_PUBLIC + +ACC_FINAL, "execute0",
"(Lcom/googlecode/aviator/utils/Env;)Ljava/lang/Object;",
"(Lcom/googlecode/aviator/utils/Env;)Ljava/lang/Object;", null);
this.mv.visitCode();
}
可以debug写到class文件查看, className文件名Script_1685767852489_58
:
b-c+a
生成的class文件
public class Script_1685767852489_58 extends ClassExpression {
private final AviatorJavaType f0;
private final AviatorJavaType f1;
private final AviatorJavaType f2;
public Script_1685767852489_58(AviatorEvaluatorInstance var1, List var2, SymbolTable var3) {
super(var1, var2, var3);
this.f2 = new AviatorJavaType("a", var3);
this.f0 = new AviatorJavaType("b", var3);
this.f1 = new AviatorJavaType("c", var3);
}
public final Object execute0(Env var1) {
return this.f0.sub(this.f1, var1).add(this.f2, var1).getValue(var1);
}
}
参数通过构造函数设置好,然后一个exceute0
方法内部就是执行b-c+a
的逻辑
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。