可实现零依赖动态规则引擎:通过java内省(propertydescriptor/map键取值)获取属性,强制类型转换(bigdecimal/trim小写/多格式布尔)保障比较一致性,手写ast解析器执行规则,并用lambdametafactory生成函数实现热加载。

不需要引入 Drools、Easy Rules 或任何第三方规则引擎库,也能实现一个真正零依赖、运行时动态加载、条件可配置的规则引擎——关键在于把强制类型转换和内省(Introspection)用对地方。
用内省替代硬编码字段访问
规则判断常要读取对象属性,比如 user.age > 18 或 order.status == "PAID"。硬写 user.getAge() 就失去动态性。内省机制能根据字符串字段名自动获取值:
- 用
Class.getDeclaredField()+setAccessible(true)直接读私有字段(适合简单 POJO) - 优先走标准 JavaBeans 规范:通过
PropertyDescriptor查找 getter 方法并调用,兼容封装良好的类 - 对 Map 类型输入(如 JSON 解析后的
Map<string object></string>),直接按 key 取值,天然支持运行时结构变化
强制类型转换解决值比较一致性
规则表达式里经常混着字符串、数字、布尔值,比如配置项是 "age >= 25",但实际传入的 age 可能是 Integer、Long 或字符串 "25"。不统一类型就无法安全比较:
- 定义通用转换策略:遇到数值类操作符(
>,, <code>==)时,把左右操作数都转为BigDecimal(兼顾精度与兼容性) - 字符串比较前统一 trim 并转小写(如
status.equalsIgnoreCase("active")) - 布尔值识别支持多种写法:
"true"、"1"、"YES"、true都转为Boolean.TRUE
规则解析与执行完全在内存中完成
所谓“零依赖”,是指不依赖外部 DSL 解析器(如 ANTLR)、不依赖脚本引擎(如 GraalVM JS)、也不依赖 Spring 表达式(SpEL)。你可以手写一个轻量级表达式解析器:
- 将规则字符串(如
"age > 18 && status == 'ACTIVE'")按运算符切分,构建抽象语法树(AST)节点 - 每个节点持有一个
evaluate(Object fact)方法,内部调用内省取值 + 强制转换 + 原生 Java 运算 - 组合规则(AND/OR)用责任链或递归方式遍历子节点,无需额外容器或上下文管理
规则热加载靠 ClassLoader + 字节码生成(可选进阶)
如果连规则类都要动态编译,可用 JavaCompiler API 编译字符串形式的 Java 代码,再用自定义 ClassLoader 加载。但更轻量的做法是:
- 规则配置存在数据库或配置中心,每次变更后触发一次 AST 重建
- 把规则逻辑封装成
Function<object boolean></object>,用 LambdaMetafactory 生成函数实例,避免反射开销 - 配合 Caffeine 缓存已编译的规则函数,首次执行稍慢,后续毫秒级响应











