如何在Spring Statemachine中检查事件是否可触发状态机而不执行转移?
状态机事件可触发性校验实现方案
你需要的仅校验不触发转移的能力,绝大多数成熟状态机框架都有内置支持,不需要基于sendEvent方法做二次改造:
- 优先使用框架内置的校验接口
不同框架的API命名略有差异:- Spring Statemachine:调用带
dryRun参数的重载方法stateMachine.sendEvent(event, true),第二个参数设为true表示试运行,仅做规则校验,不会修改状态机状态、也不会执行转移绑定的业务动作,返回值和原方法一致,true代表事件可触发转移。 - Cola Statemachine:直接调用
stateMachine.accept(event)方法,该方法本身就仅做转移合法性校验,不会产生任何实际状态变更。 - 其他框架基本都有类似
canFire/isAllowed命名的专用校验方法,可以直接查对应框架的API文档使用。
- Spring Statemachine:调用带
- 自研状态机的实现思路
如果用的是自研状态机没有内置校验能力,可以自己实现校验逻辑:先获取状态机当前状态,遍历该状态绑定的所有转移规则,匹配事件类型、守卫(Guard)条件是否全部满足,匹配成功即代表事件可触发,全程不要修改状态机的状态字段、也不要调用转移绑定的Action逻辑即可。 - 避坑提示
不要用「调用sendEvent后手动回滚状态」的方式实现校验,这种方式会执行转移绑定的副作用逻辑(比如数据库写入、消息推送等),大概率会产生脏数据。
多线程场景下注意:校验和实际触发转移的操作要加锁保证原子性,避免校验通过后、实际发送事件前状态机被其他线程修改,导致校验结果和实际执行结果不一致。
内容的提问来源于stack exchange,提问作者batuhancan
相关产品推荐
相关产品推荐

