规则的加载与管理者——KieContainer的获取与其类型的区别(虽然标题是KieContainer,其实说的还是KieServices)

news2024/9/27 23:33:36

之前梳理了一下有关KieServices的获取,与获取中的代码走向,详情请见:

“万恶”之源的KieServices,获取代码就一行,表面代码越少里面东西就越多,本以为就是个简单的工厂方法,没想到里面弯弯绕绕这么多东西_zcrazy胡说八道的博客-CSDN博客

在我使用drools时,第一行的语句就是获取KieServices,紧接着就是获取KieContainer,就是下面这一句

代码1

KieContainer kContainer = kieServices.getKieClasspathContainer();

然后我就去看了这个getKieClasspathContainer方法的源码,源码如下:

代码2 KieServicesImpl类中的getKieClasspathContainer方法

/**
* 获取类路径容器
* 
* @param containerId 容器Id
* @param classLoader 类加载器
* @return Kie容器
*/
public KieContainer getKieClasspathContainer(String containerId, ClassLoader classLoader) {
    if (this.classpathKContainer == null) {
        //如果是第一次调用该方法,这个classpathKContainer肯定是null的
        //这个变量会在if处理中进行初始化
        synchronized(this.lock) {
            //下面的内容为同步内容
            if (this.classpathKContainer == null) {
                //将传入的类加载器赋值给当前实例
                this.classpathClassLoader = classLoader;
                if (containerId == null) {
                    //如果containerId是null的,则会给当前实例赋值一个UUID作为containerId
                    this.classpathKContainerId = UUID.randomUUID().toString();
                } else {
                    this.classpathKContainerId = containerId;
                }
                //会调用KieServices的两个创建方法
                this.classpathKContainer = this.newKieClasspathContainer(
                                                this.classpathKContainerId, 、
                                                classLoader);
            } else if (classLoader != this.classpathClassLoader) {
                throw new IllegalStateException("There's already another KieContainer created from a different ClassLoader");
            }
        }
    } else if (classLoader != this.classpathClassLoader) {
        throw new IllegalStateException("There's already another KieContainer created from a different ClassLoader");
    }

    if (containerId != null && !this.classpathKContainerId.equals(containerId)) {
        throw new IllegalStateException("The default global singleton KieClasspathContainer was already created with id " + this.classpathKContainerId);
    } else {
        return this.classpathKContainer;
    }
}

里面的注释是我添加的,如果在正常情况下,第一次调用该方法,会直接进入到newKieClasspathContainer方法中去,源码如下:

代码3 KieServicesImpl中的newKieClasspathContainer方法

public KieContainer newKieClasspathContainer(String containerId, 
                                                ClassLoader classLoader, 
                                                ReleaseId releaseId) {
    KieContainerImpl newContainer;
    if (containerId == null) {
        //如果containerId为null
        newContainer = new KieContainerImpl(UUID.randomUUID().toString(), 
                        new ClasspathKieProject(classLoader, this.listener, releaseId), 
                        (KieRepository)null);
        return newContainer;
    } else if (this.kContainers.get(containerId) == null) {
        //containerId不为null,但是kContainers映射中没有该containerId
        newContainer = new KieContainerImpl(containerId, 
                        new ClasspathKieProject(classLoader, this.listener, releaseId), 
                        (KieRepository)null, 
                        releaseId);
        KieContainer check = 
            (KieContainer)this.kContainers.putIfAbsent(containerId, newContainer);
        if (check == null) {
            //如果check为null,说明kContainers中没有当前的containerId,返回newContainer。
            return newContainer;
        } else {
            //如果check不为null,说明kContainers已经有当前containerId
            newContainer.dispose();
            throw new IllegalStateException("There's already another KieContainer created with the id " + containerId);
        }
    } else {
        throw new IllegalStateException("There's already another KieContainer created with the id " + containerId);
    }
}

注释也是我自己添加的,最终就是会返回一个KieContainerImpl的实例,到这里,基本就已经返回一个KieContainer了,工作就结束了,但是凡事就怕琢磨,这个KieContainer到底是个什么呢?

KieContainer:是用于加载和管理规则资源的核心组件

规则资源又是什么呢?

规则资源(Rule Resources)指的是包含业务规则定义的文件,这些规则文件描述了系统在特定条件下应该如何进行推理或决策。

这些规则资源文件通常以.drl、.xls、.dslr、.bpmn等扩展名保存

简单来说,就是咱们项目里面的drl文件需要KieContainer加载,可能后续还有移除,更新,添加等等跟管理相关的操作。

回到代码1中我发现getKieClasspathContainer这个方法,方法名有问题,为什么不是getContainer,而是getKieClasspathContainer,这说明这个Container是由不同种类的,于是我在KieService中又发现了这个方法newKieContainer,为什么有了newKieClasspathContainer,还会有个newKieContainer方法呢?于是我就看了一下源码:

代码4 KieServicesImpl中的newKieContainer方法

public KieContainer newKieContainer(String containerId, 
                                        ReleaseId releaseId, 
                                        ClassLoader classLoader) {
    InternalKieModule kieModule = (InternalKieModule)this.getRepository().
                                            getKieModule(releaseId);
    if (kieModule == null) {
        throw new RuntimeException("Cannot find KieModule: " + releaseId);
    } else {
        if (classLoader == null) {
            classLoader = kieModule.getModuleClassLoader();
        }

        KieProject kProject = new KieModuleKieProject(kieModule, classLoader);
        if (classLoader != kProject.getClassLoader()) {
            kProject.init();
        }

        KieContainerImpl newContainer;
        if (containerId == null) {
            newContainer = new KieContainerImpl(UUID.randomUUID().toString(), 
                                                    kProject, 
                                                    this.getRepository(), 
                                                    releaseId);
            return newContainer;
        } else if (this.kContainers.get(containerId) == null) {
            newContainer = new KieContainerImpl(containerId, 
                                                    kProject, 
                                                    this.getRepository(), 
                                                    releaseId);
            KieContainer check = (KieContainer)this.kContainers.putIfAbsent(containerId, 
                                                                           newContainer);
            if (check == null) {
                return newContainer;
            } else {
                newContainer.dispose();
                throw new IllegalStateException("There's already another KieContainer created with the id " + containerId);
            }
        } else {
            throw new IllegalStateException("There's already another KieContainer created with the id " + containerId);
        }
    }
}

总体来说newKieContainer方法和newKieClasspathContainer方法的代码很像,但是多出了几步,多出了KieModule的获取,以及KieProject 的获取,从代码里来看获取KieModule就是为了获取KieProject,然后在实例化KieContainerImpl时,让这个KieProject作为参数输入,在newKieClasspathContainer中也有出现KieProject,只不过在newKieClasspathContainer中出现的是ClasspathKieProject,而在newKieContainer中出现的是KieModuleKieProject。

KieServices类提供了两种方法来创建KieContainer对象,分别是newKieClasspathContainer()和newKieContainer(),他们的区别如下:

  • newKieClasspathContainer()

    • 从类路径(classpath)加载规则资源。规则资源通常位于项目的src/main/resources目录下或其他在类路径中的位置。

    • 可以自动扫描类路径中的规则文件并加载它们。

    • 适用于需要将规则文件打包到应用程序中,并在运行时从类路径加载规则资源的场景。

  • newKieContainer(groupId, artifactId, version)

    • 通过Maven坐标(groupId、artifactId和version)指定规则资源的位置。

    • 需要在Maven仓库中存在相应的规则资源(JAR包)。

    • 适用于从远程Maven仓库或本地Maven仓库加载规则资源的场景。

总结

在KieServices中,实例化KieContainer其实就两个方法,一个是从类路径加载规则资源的newKieClasspathContainer,一个是从Maven仓库中加载资源的newKieContainer,如果直接使用getKieClasspathContainer,第一次用会默认使用newKieClasspathContainer,之后再使用就是可以直接获取KieServicesImpl实例中对应的KieContainer。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/889432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3跳转页面后 海康监控实例不销毁

第一个页面是这样的 跳转到新的页面 只有海康的监控没有消失 使用控制台审查元素也审查不到 解决方法:在vue3的销毁周期把海康的监控销毁掉 import { reactive, onDeactivated} from "vue"; const state reactive({oWebControl: null as any, //监控绑…

数字乡村三维可视化监控管理平台

数字乡村是伴随网络化、信息化和数字化在农业农村经济社会发展中的应用,既是乡村振兴的战略方向,也是建设数字中国的重要内容。为了进一步提升乡村治理智能化、专业化水平,解决建设顶层缺失、数据孤岛等问题,数字孪生技术被广泛应…

16.4 【Linux】特殊文件与程序

16.4.1 具有 SUID/SGID 权限的指令执行状态 SUID 的权限其实与程序的相关性非常的大!为什么呢?先来看看 SUID 的程序是如何被一般使用者执行,且具有什么特色呢? SUID 权限仅对二进制程序(binary program)…

LL库实现SPI MDA发送方式驱动WS2812

1,首先打卡STM32CubeMX,配置一下工程,这里使用的芯片是STM32F030F4P6。 时钟 SPI外设 SPI DMA 下载接口,这个不配置待会下程序后第二次就不好下载调试了。 工程配置,没啥说的 选择生成所有文件 将驱动都改为LL库 然后直…

python知识:什么是字符编码?

前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 我们的MySQL使用latin1的默认字符集, 也就是说,对汉字字段直接使用GBK内码的编码进行存储, 当需要对一些有汉字的字段进行拼音排序时(特别涉及到类似于名字这样的字段时…

【Mysql 连接报错】

文章目录 遇到问题查看用户信息修改加密规则成功连入mysql 遇到问题 socket: auth failed …/…/lualib/skynet/socketchannel.lua:482: errno:1251, msg:Client does not support authentication protocol requested by server; consider upgrading MySQL client,sqlstate:080…

高效解决Anaconda Prompt报错Did not find VSINSTALLDIR这类问题

文章目录 回忆问题解决问题step1step2 回忆问题 类似于划红线部分然后还有很多行的报错信息,最后一行肯定是红色划线部分 解决问题 step1 找到 D:\Anaconda\envs\pytorch\etc\conda\activate.d在这个文件夹内会有两个文件,删除 vs2017_compiler_v…

Java版本+企业电子招投标系统源代码+支持二开+Spring cloud tbms

​ 项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以…

考研算法第46天: 字符串转换整数 【字符串,模拟】

题目前置知识 c中的string判空 string Count; Count.empty(); //正确 Count ! null; //错误c中最大最小宏 #include <limits.h>INT_MAX INT_MIN 字符串使用发运算将字符加到字符串末尾 string Count; string str "liuda"; Count str[i]; 题目概况 AC代码…

桃红葡萄酒的品尝笔记记录

桃红葡萄酒通常都是用红葡萄品种来制作的&#xff0c;葡萄皮接触和saign方法会降低葡萄酒中的红色。因此&#xff0c;歌海娜、西拉、赤霞珠、坦普拉尼洛、桑娇维塞、马尔贝克、穆韦德、佳丽酿、仙粉黛、辛索和黑皮诺都是用于桃红葡萄酒甚至混合葡萄酒的常见品种。味道偏向水果味…

常见的逻辑运算符

计算机组成原理常见的逻辑运算符及其真值规则 逻辑运算名称 符号 规则 与运算 同真则真&#xff0c;有假则假 或运算 有真则真&#xff0c;同假则假 非运算 非真为假&#xff0c;非假为真 异或逻辑 相同为假&#xff0c;不同为真 与非逻辑 将与运算…

【数据分析入门】Numpy进阶

目录 一、数据重塑1.1 透视1.2 透视表1.3 堆栈/反堆栈1.3 融合 二、迭代三、高级索引3.1 基础选择3.2 通过isin选择3.3 通过Where选择3.4 通过Query选择3.5 设置/取消索引3.6 重置索引3.6.1 前向填充3.6.2 后向填充 3.7 多重索引 四、重复数据五、数据分组5.1 聚合5.2 转换 六、…

depcheck 检查依赖插件使用及报错

1.全局安装 npm i depcheck -g 2.使用depcheck 指令进行依赖检查 报错 &#xff1a; 无法加载 xxx\npm\depcheck.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。…

AI绘图(9)stable diffusion Lora 用法

Lora模型是配合Stable Diffusion使用的。可以简单的把Lora当成化妆师&#xff0c;当Stable Difusion生成的人不好看时&#xff0c;使用Lora可以帮它化妆&#xff0c;让它从丑小鸭变成白天鹅。 简单来说&#xff1a;就是一个修饰作用。 使用文生图功能 1、不使用Lora模型 Pr…

10、Redis单线程 VS 多线程

Redis单线程 VS 多线程 redis到底是单线程还是多线程&#xff1f; IO多路复用听说过吗&#xff1f; redis为什么快&#xff1f; 2、Redis为什么选择单线程&#xff1f; 这种问法其实并不严谨&#xff0c;为啥这么说呢? Redis的版本很多3.x、4.x、6.x&#xff0c;版本不同架构…

【2024】MySQL中常用函数和窗口函数的基本使用方式

MySQL中常用函数和窗口函数的基本使用方式 一、基础函数1、聚合函数&#xff1a;2、字符串函数&#xff1a;3、日期和时间函数4、数值函数5、条件函数 二、窗口函数(*OVER*) 一、基础函数 1、聚合函数&#xff1a; SELECT COUNT(*) FROM table_name;&#xff1a;计算表中的行…

在不破坏原有隔离状态的情况下,怎么实现网间数据安全摆渡?

随着网络技术的演进&#xff0c;网络攻击、数据窃取、数据泄露事件也愈发频繁&#xff0c;给企业造成损失和负面影响&#xff0c;企业数据防泄漏治理是大趋势&#xff0c;也是自身迫切需求。 2021年1月&#xff0c;中国农业银行因存在数据泄露风险、互联网门户网站泄露敏感信息…

数据接入体验再升级!TDengine 推出支持 MQTT 协议的数据接入功能

我们非常高兴地宣布&#xff0c;TDengine 企业版和 TDengine Cloud 正式推出重磅功能&#xff0c;这一功能主打无缝数据接入支持&#xff0c;旨在帮助用户彻底改善数据接入体验。作为一款创新性的解决方案&#xff0c;TDengine 企业版和 TDengine Cloud 可以直接将 MQTT 服务器…

使用YOLOV5训练自己的数据集时所遇到问题|PyYAML|KeyError

训练过程中&#xff1a; 1、attributeerror: module yaml has no attribute load 方法1&#xff1a; 如果另一个名为 yaml.py 的文件在 PyYaml 库之前出现在你的 sys.path 中&#xff0c;就会接收并导入该 yaml.py 文件。如将文件命名为 yaml.py。 import yaml 正在加载 ya…

<kernel>kernel 6.4 USB-之-port_event()分析

&#xff1c;kernel&#xff1e;kernel 6.4 USB-之-port_event()分析 kernel 6.4 USB系列文章如下&#xff1a; &#xff1c;kernel&#xff1e;kernel 6.4 USB-之-hub_event()分析 &#xff1c;kernel&#xff1e;kernel 6.4 USB-之-port_event()分析 本文是基于linux kerne…