一、equality modes 介绍
在 drools
中存在如下 2 种 equality modes。
1、identity 模式
identity
:这是默认的状况。drools 引擎应用 IdentityHashMap
保留所有插入到工作内存中的 Fact
对象。对于每次插入一个新的对象,则会返回一个新的 FactHandle
对象。如果是反复插入对象,则返回曾经存在的 FactHandle
对象。
举例:
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
针对以上例子,factHandle1 != factHandle2
然而 factHandle2 == factHandle3
。即工作内存中会存在 2 个 Person
对象。
2、equality 模式
equality
:drools 引擎应用 HashMap
保留所有插入到工作内存中的 Fact
对象。在这种模式下,如果向 drools 中插入一个新的对象,只有这个对象不存在 ( 依据对象的 hashcode
和equals
判断 ) 才会返回一个新的 FactHandle
否则返回曾经存在的FactHandle
。
举例:
// 重写了 Person 对象的 hashcode 和 equals 办法
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
针对以上例子,factHandle1 == factHandle2
然而 factHandle2 == factHandle3
。即工作内存中会存在 1 个 Person
对象。
二、需要
咱们存在一个 Person
对象,存在如下 3 个属性 name,age 和 address
,其中重写对象的name 和 age
的 hashcode 和 equals 办法。
- 屡次向工作内存中插入对象,看产生的后果。
- 插入同一个对象看获取到的 FactHandle 对象是否是同一个。
三、如何设置 fact 对象的 equality 行为
此处介绍一个通过 kmodule.xml
配置的办法
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase-identity" packages="rules" default="false" equalsBehavior="identity">
<ksession name="ksession-01" default="false" type="stateful"/>
</kbase>
<kbase name="kbase-equality" packages="rules" default="false" equalsBehavior="equality">
<ksession name="ksession-02" default="false" type="stateful"/>
</kbase>
</kmodule>
通过上方的代码可知是通过配置 kbase
下的 equalsBehavior
属性来配置。
其余的配置办法,参考下图:
四、编码实现
1、我的项目结构图
2、倒入 jar 包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-bom</artifactId>
<type>pom</type>
<version>7.69.0.Final</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-mvel</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.11</version>
</dependency>
</dependencies>
3、编写 Person 对象
public class Person {
private String name;
private Integer age;
private String address;
public Person(String name, Integer age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
public String getAddress() {return address;}
public void setAddress(String address) {this.address = address;}
@Override
public boolean equals(Object o) {if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) && Objects.equals(age, person.age);
}
@Override
public int hashCode() {return Objects.hash(name, age);
}
}
留神:
此对象须要重写 hashcode 和 equals 办法。
4、编写 kmodule.xml 文件
在此配置文件中,须要在 kbase
上指定 equalsBehavior
,用来确定Fact
对象的 equality modes。
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase-identity" packages="rules" default="false" equalsBehavior="identity">
<ksession name="ksession-01" default="false" type="stateful"/>
</kbase>
<kbase name="kbase-equality" packages="rules" default="false" equalsBehavior="equality">
<ksession name="ksession-02" default="false" type="stateful"/>
</kbase>
</kmodule>
留神:
须要看 2 个 equalsBehavior
的取值
5、编写一个规定文件
package rules
import com.huan.drools.Person
// 定义规定
rule "rule_01"
when
$p: Person()
then
System.out.println(Thread.currentThread().getName() + "name:"+$p.getName()+"age:"+$p.getAge());
end
规定文件中的内容很简略,只有工作内存中存在 Person
对象,那么就输入这个对象的 name
和age
的值。
6、identity 模式测试
1、编写测试代码
public class DroolsApplication {public static void main(String[] args) {equalsBehaviorIdentity();
}
private static void equalsBehaviorIdentity() {KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
// 留神此处的 ksession-01
KieSession kieSession = kieContainer.newKieSession("ksession-01");
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
kieSession.fireAllRules();
kieSession.dispose();}
}
2、运行后果
具体的解释见上图中的阐明。
7、equality 模式测试
1、编写测试代码
public class DroolsApplication {public static void main(String[] args) {equalsBehaviorEquality();
}
private static void equalsBehaviorEquality() {KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("ksession-02");
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
kieSession.fireAllRules();
kieSession.dispose();}
}
2、运行后果
五、论断
针对如下代码,看看在不同 equality modes 下的行为
Person p1 = new Person("zhangsan", 20, "湖北罗田");
Person p2 = new Person("zhangsan", 20, "湖北黄冈罗田");
FactHandle factHandle1 = kieSession.insert(p1);
FactHandle factHandle2 = kieSession.insert(p2);
FactHandle factHandle3 = kieSession.insert(p2);
Person
对象的 hashcode 和 equals
办法进行重写了,依据构造方法的前 2 个参数。
1、identity 模式下
factHandle1 != factHandle2
因为 p1 和 p2 是 2 个不同的对象。factHandle2 == factHandle3
因为是 p2 反复退出工作内存,这个时候工作内存中曾经存在了,所以返回之前关联的FactHandle
2、equality 模式下
factHandle1 == factHandle2 == factHandle3
因为这种模式下,是须要依据对象的 equals
和hashcode
办法进行比拟,而 Person
对象重写了这 2 个办法,所以返回的是同一个。
六、残缺代码
https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-fact-equality-modes
七、参考链接
1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#fact-equality-modes-con_decision-engine