暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

easy-rules系列——Core源码分析

weiyanweiyu 2021-06-24
3114

easy-rules系列——Core源码分析

easy-rules仓库地址,开源协议是MIT。

本文是基于easy-rules的4.0.0版本。

作者:weiyiysw

邮箱:weiyiysw@163.com

本文章采用CC BY-NC-ND 4.0 许可协议进行许可

easy-rules是什么

Easy Rules是一个Java语言的规则引擎,由Martin Fowler的一篇文章Should I use a Rules Engine?启发而完成的。Martin说

You can build a simple rules engine yourself. All you need is to create a bunch of objects with conditions and actions, store them in a collection, and run through them to evaluate the conditions and execute the actions.

Easy Rules就是基于此诞生的。Easy Rules的源码相当简单,并且对于理解规则引擎也是很有帮助。

Easy Rules的核心特性包括:

  • API简单,轻量级的库

  • 可以基于POJO开发,以及annotation的编程模型

  • 具备从基本规则创建合成复合规则

  • 支持SpEL和MVEL

easy-rules源码导读

我们先来看下easy-rules的项目的整体结构

➜  easy-rules git:(master) tree -L 1
.
├── easy-rules-archetype
├── easy-rules-core
├── easy-rules-mvel
├── easy-rules-spel
├── easy-rules-support
├── easy-rules-tutorials

从以上项目结构中可以看到,archetype是maven的骨架,可基于这个生成基础的项目。tutorials是使用demo,如果只关心如何使用,查看这个项目即可。

阅读源码,那么我们需要关注的是

  • easy-rules-core:规则引擎的核心逻辑

  • easy-rules-mvel:提供MVEL的支持

  • easy-rules-spel:提供SpELl的支持

  • easy-rules-support:将基本规则组合成复合规则

easy-rules-core源码

core的源码分为3个package

  • annotation:通知,可基于通知生成规则

  • api:定义了规则、事实接口

  • core:主要是规则引擎的实现

规则引擎core分析

规则引擎的三要素:事实对象、规则逻辑、规则动作。

规则引擎启动后,基于现有的事实对象,进行逻辑判断,当逻辑判断为true
时,则执行规则动作,为false
时,不执行规则动作。

规则引擎关心的是处理过程中的复杂条件组合,能做到动态的修改规则逻辑而无需更改任何代码。

annotation

annotation包里有5个通知,分别是Action、Condition、Fact、Priority、Rule。这5个通知是用来定义规则及事实的。

api

规则接口:Action、Condition、Rule。

通过规则接口实现规则的定义。

Rule接口具有优先级,默认的情况下,数字越小代表优先级越高。Rule接口继承Comparable接口,支持大家自定义自己的规则优先级。一般来说,默认的即满足使用。

规则监听器接口:RuleListener、RulesEngineListener。
RuleListener

此接口和规则相关,规则执行的监听器,用以“生命周期”各个阶段类比,可包含以下阶段,并在各个阶段进行自定义监听。

各个阶段包括:规则触发前、规则触发后、动作执行前、动作执行后、触发并执行成功、触发并执行失败、规则逻辑触发失败。

RulesEngineListener

顾名思意,规则引擎的监听器。可监听的阶段为:规则执行之前、规则执行之后。

规则引擎接口:RuleEngine

如果觉得内置的规则引擎不合适,可实现此接口,自定义规则引擎。

Fact与Facts

Fact类是事实对象的泛型类,一个Fact对象对应一个事实对象。

Facts是Fact事实对象的集合,内部实现为Set集合。

Rules

Rules类是规则的集合,内部以TreeSet存储。前面有说到,规则包含属性Priority
,数字越小优先级越高。

我们制定的规则,需要注册到Rules对象中。也可以从Rules对象中移除规则。

规则引擎参数

目前有4个规则引擎参数

  • skipOnFirstAppliedRule

  • skipOnFirstNonTriggeredRule

  • skipOnFirstFailedRule

  • prioityThreshold

3个skip的boolean参数,相信大家看名字也能知道其作用。最后一个优先级阈值的参数是int
类型,其作用是跳过超过用户定义的优先级阈值的规则。默认的情况下,这个参数值是Integer.MAX_VALUE
。比如,在规则引擎里,我们设置prioityThreshold = 10
,那么,规则集合里(Rules)所有优先级大于10的都会被跳过,不会执行。

DefaultRulesEngine
中,规则参数会应用到所有的规则,且prioityThreshold = 10
的情况下,优先级小于等于10的所有规则都会执行。

InferenceRulesEngine
中,规则参数只会应用到候选(candidate)规则上,且prioityThreshold = 10
的情况下,优先级小于等于10的所有规则都会执行。那么,什么是候选规则呢?在这个规则引擎中,规则集(Rules)里会对所有规则进行逻辑判断,当逻辑判断结果为true
时,会进入到候选规则上。对应的源码如下:

private Set<Rule> selectCandidates(Rules rules, Facts facts) {
       Set<Rule> candidates = new TreeSet<>();
       for (Rule rule : rules) {
           if (rule.evaluate(facts)) {
               candidates.add(rule);
          }
      }
       return candidates;
  }

core

core包中的源码,重点看规则引擎(RuleEngine)的源码以及规则代理(RuleProxy)。

规则引擎

我们先来看下规则引擎的类图。

如上,easy-rules实现了2个规则引擎,DefaultRulesEngine
InferenceRulesEngine

先来看默认的规则引擎,关注2个方法,fire
方法以及内置的doFire
方法。

@Override
public void fire(Rules rules, Facts facts) {
   triggerListenersBeforeRules(rules, facts);
   doFire(rules, facts);
   triggerListenersAfterRules(rules, facts);
}

可以看到,fire
方法中,前后执行RuleEngineListener
的接口。真正执行的逻辑在doFire
中。

接下来,我们看一下doFire
逻辑

代码很长,部分会省略,省略的以 ... 表示

void doFire(Rules rules, Facts facts) {
   // check rules is not empty
   //...
   
   // log engineParameters rules facts
   //...
   
   for (Rule rule : rules) {
       // 判断规则的优先级与规则引擎的参数优先级
       //
       // ...
       boolean evaluationResult = false;
       try {
           // 根据事实,检查规则的逻辑条件是否为true
      evaluationResult = rule.evaluate(facts);
      } catch() {
           //...
      }
       // 规则的逻辑条件为true
       if (evaluationResult) {
      //...
           // 执行规则
           rule.execute(facts);
           //...
      }
  }
}

以上,就是doFire
的核心逻辑了。

省略的部分都是RuleListener
的接口,以便你可以在规则执行的过程中,进行监听,并进行加入自己的代码逻辑。


文章转载自weiyanweiyu,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论