rulebook 简单记录
總體:
- 最后發版為2018年
- 相比EASY RULE,不支持jexl等腳本語言
- 支持Spring
- 內部執行都是使用jdk proxy模式,無論是annotation還是builder模式
- 可以使用CoRRuleBook 實現chain模式,在chain內按order進行執行
- 一個rule里面可以有多個action(@Then),多個fact(@Given),多個condition(@When),但注意When只有一個會執行
- 支持將一個java package的所有rule類組成一個Chain-CoRRuleBook
- 支持audit
核心概念
Much like the Given-When-Then language for defining tests that was popularized by BDD, RuleBook uses a Given-When-Then language for defining rules. The RuleBook Given-When-Then methods have the following meanings.
- Given some Fact(s)
- When a condition evaluates to true
- Then an action is triggered
核心類及示意代碼
rule執行類:GoldenRule
/**
A standard implementation of {@link Rule}.
@param the fact type
@param the Result type
*/
public class GoldenRule<T, U> implements Rule<T, U> {
action 識別代碼
public List<Object> getActions() {if (_rule.getActions().size() < 1) {List<Object> actionList = new ArrayList<>();for (Method actionMethod : getAnnotatedMethods(Then.class, _pojoRule.getClass())) {actionMethod.setAccessible(true);Object then = getThenMethodAsBiConsumer(actionMethod).map(Object.class::cast).orElse(getThenMethodAsConsumer(actionMethod).orElse(factMap -> { }));actionList.add(then);}_rule.getActions().addAll(actionList);}return _rule.getActions(); }condition 設置和獲取,可以手工指定condition 如:auditableRule.setCondition(condition);
如果沒有設置,使用如下代碼識別
注意findFirst,代表只有一個生效
Chain 管理類 CoRRuleBook 使用Reflections 識別package下所有rule類的核心代碼如下:
/*** Gets the POJO Rules to be used by the RuleBook via reflection of the specified package.* @return a List of POJO Rules*/protected List<Class<?>> getPojoRules() {Reflections reflections = new Reflections(_package);List<Class<?>> rules = reflections.getTypesAnnotatedWith(com.deliveredtechnologies.rulebook.annotation.Rule.class).stream().filter(rule -> _package.equals(rule.getPackage().getName())) // Search only within package, not subpackages.filter(rule -> rule.getAnnotatedSuperclass() != null) // Include classes only, exclude interfaces, etc..collect(Collectors.toList());rules.sort(comparingInt(aClass ->getAnnotation(com.deliveredtechnologies.rulebook.annotation.Rule.class, aClass).order()));return rules;}Fact管理
/*** A Fact is a single piece of data that can be supplied to a {@link Rule}.* Facts are not immutable; they may be changed by rules and used to derive a result state.*/ public class Fact<T> implements NameValueReferable<T> {private String _name;private T _value;/*** A FactMap decorates {@link Map}; it stores facts by their name and provides convenience methods for* accessing {@link Fact} objects.*/ public class FactMap<T> implements NameValueReferableMap<T> {private Map<String, NameValueReferable<T>> _facts;public FactMap(Map<String, NameValueReferable<T>> facts) {_facts = facts;}實際上有點key重復的感覺,每個fact 本身還有name和value
Then/action 的執行核心代碼 在goldenRule里面
//invoke the actionStream.of(action.getClass().getMethods()).filter(method -> method.getName().equals("accept")).findFirst().ifPresent(method -> {try {method.setAccessible(true);method.invoke(action,ArrayUtils.combine(new Object[]{new TypeConvertibleFactMap<>(usingFacts)},new Object[]{getResult().orElseGet(() -> result)},method.getParameterCount()));if (result.getValue() != null) {_result = result;}} catch (IllegalAccessException | InvocationTargetException err) {LOGGER.error("Error invoking action on " + action.getClass(), err);if (_actionType.equals(ERROR_ON_FAILURE)) {throw err.getCause() == null ? new RuleException(err) :err.getCause() instanceof RuleException ? (RuleException)err.getCause() :new RuleException(err.getCause());}}});facts.putAll(usingFacts); }多fact示意
fact 通過@Given進行命名
@Rule public class HelloWorld {@Given("hello")private String hello;@Given("world")private String world;然后復制
facts.setValue("hello", "Hello"); facts.setValue("world", "World");Spring 使用
@Configuration @ComponentScan("com.example.rulebook.helloworld") public class SpringConfig { @Bean public RuleBook ruleBook() { RuleBook ruleBook = new SpringAwareRuleBookRunner("com.example.rulebook.helloworld"); return ruleBook; } }擴展
可以擴展rule類,參考RuleAdapter
public RuleAdapter(Object pojoRule, Rule rule) throws InvalidClassException {com.deliveredtechnologies.rulebook.annotation.Rule ruleAnnotation =getAnnotation(com.deliveredtechnologies.rulebook.annotation.Rule.class, pojoRule.getClass());if (ruleAnnotation == null) {throw new InvalidClassException(pojoRule.getClass() + " is not a Rule; missing @Rule annotation");}_actionType = ruleAnnotation.ruleChainAction();_rule = rule == null ? new GoldenRule(Object.class, _actionType) : rule;_pojoRule = pojoRule; }擴展RuleBook(The RuleBook interface for defining objects that handle the behavior of rules chained together.)
/*** Creates a new RuleBookRunner using the specified package and the supplied RuleBook.* @param ruleBookClass the RuleBook type to use as a delegate for the RuleBookRunner.* @param rulePackage the package to scan for POJO rules.*/public RuleBookRunner(Class<? extends RuleBook> ruleBookClass, String rulePackage) {super(ruleBookClass);_prototypeClass = ruleBookClass;_package = rulePackage;}當然chain類也可以自己寫。
其它
使用predicate的test 來判斷condition 來
boolean test(T t)
Evaluates this predicate on the given argument.
Parameters:
t - the input argument
Returns:
true if the input argument matches the predicate, otherwise false
使用isAssignableFrom 來判斷輸入的fact 是否滿足rule類里面的定義
isAssignableFrom是用來判斷子類和父類的關系的,或者接口的實現類和接口的關系的,默認所有的類的終極父類都是
Object。如果
A.isAssignableFrom(B)結果是true,證明
B可以轉換成為
A,也就是
A可以由
B轉換而來
總結
以上是生活随笔為你收集整理的rulebook 简单记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 质量frr_【转】 FAR FRR EE
- 下一篇: 解决使用360安装windows更新后启