Drools中能否向KieBase添加POJO fact类?如何获取关联的fact类?
Drools 框架常见问题解答
是否支持向KieBase中添加POJO Fact类
完全支持。Drools的KieBase在构建时会自动通过绑定的类加载器识别、关联规则中引用的POJO类,不存在“需要手动将POJO类注册到KieBase”的强制要求——只要类对KieBase的类加载器可见,规则中正确引用了对应类的全限定名(或同包自动导入),就可以正常作为Fact对象传入KieSession执行规则。
需要明确的是:KieBase没有提供公开的“向已构建完成的实例中手动追加POJO类”的原生API,所有类的关联都是在KieBase构建阶段通过类加载器完成的,构建完成后再追加外部类时,必须重新构建KieBase才能生效。
如何从KieBase中获取关联的Fact类
KieBase没有直接暴露“已关联Fact类列表”的公开原生接口,可以通过两种稳定路径实现获取:
- 基于Maven包结构约定获取:按照DRL与Fact类同包存放的规则,在打包规则Jar时,为每个DRL模块生成一份轻量元数据(比如properties文件,记录每个规则包下对应的Fact类全限定名),动态拉取Maven仓库的Jar包时,直接读取元数据拿到类名,再通过
KieContainer绑定的类加载器加载即可。这种方式稳定性高、性能好,不需要额外依赖内部解析逻辑。 - 基于规则元数据解析获取:遍历
KieBase下所有已注册的KiePackage,读取每个包下所有Rule的左侧(LHS)条件约束,提取所有引用的对象类型引用,去重后就是该KieBase涉及的全部Fact类。这种方式不需要额外维护元数据,但需要依赖Drools内部的规则AST解析API,版本兼容性需要提前验证。
既定实现方案的可行性评估
“在Maven仓库下将DRL规则文件与其对应的fact类放置在相同包路径下实现关联,从仓库中动态获取KieBase,从中取出对应的fact类实例化后传入KieSession执行规则”的整体方案可落地,但需要规避几个常见实现坑:
- 构建Kie容器时,必须给
KieBuilder、KieModule绑定独立的、和Maven拉取Jar包一致的类加载器,避免多版本规则包共存时出现类转换错误、类找不到的问题。 - 不要尝试通过反射读取
KieBase的私有字段去获取内部类定义,这种方式在Drools版本升级时极易失效,维护成本极高。 - 如果Fact类的结构变更不频繁,不要每次拉取规则Jar时都重新加载类,要复用类加载器的缓存,避免内存溢出。
可替代的技术实现方案
如果上述方案存在维护成本高、类冲突风险大的问题,可以根据业务场景选择以下替代方案:
- 公共依赖拆分方案:把所有Fact类抽到独立的公共基础依赖模块,规则Jar包只存放DRL文件,不重复打包Fact类。这种场景下根本不需要从
KieBase中“获取Fact类”——Fact类作为公共依赖直接引入项目即可,直接正常实例化后传入KieSession,类加载冲突风险最低,运行性能最好。 - DRL内嵌类型方案:如果Fact类的结构需要跟着规则频繁变更,可以直接在DRL文件中用
declare语句定义事实结构,不需要外部POJO类。这种场景下可以直接通过KieBase的getFactType(包名, 类名)方法拿到对应的事实类型,用Drools提供的事实实例化工厂直接生成实例,灵活性最高。 - 原生KieContainer加载方案:直接使用Drools原生的Maven整合能力,通过
KieServices从Maven仓库动态拉取规则Jar(含同包的Fact类),绑定专属的KieContainer,后续实例化、执行规则的全流程都通过KieContainer的类加载器完成,不需要额外做类关联逻辑,Drools内部会处理所有加载细节。
内容的提问来源于stack exchange,提问作者Amado Gonzalez
相关产品推荐
相关产品推荐

