Spring State Machine 4.0.0 JOIN组件异常行为咨询
Spring State Machine 4.0.0 JOIN 行为不符合预期的原因与修复
你的问题出在Spring State Machine 4.0.0中JOIN转换的默认模式上。默认情况下,JOIN采用Cumulative模式:只要正交分支的状态机曾经进入过JOIN指定的所有源状态(L2和R2),就会触发JOIN转换,而不要求这些状态当前处于激活状态。这就解释了为什么你先把L区域切到L2再切回L1,之后R区域切到R2时,JOIN直接触发——因为L分支已经到达过L2,满足了Cumulative模式的条件。
修复方案
在JOIN转换的配置中,显式指定使用Synchronous模式,该模式要求所有正交分支当前都处于JOIN的源状态时才会触发转换。修改你的转换规则代码如下:
transitions .withExternal() .source(I) .target(FORK) .event(S) .and() .withFork() .source(FORK) .target(L1).target(R1) .and() .withExternal() .source(L1) .target(L2) .event(TIK) .and() .withExternal() .source(L2) .target(L1) .event(TOK) .and() .withExternal() .source(R1) .target(R2) .event(FUZ) .and() .withExternal() .source(R2) .target(R1) .event(BAZ) .and() .withJoin() .source(R2).source(L2) .target(JOIN) // 显式指定同步模式,要求当前所有源状态同时激活 .mode(JoinMode.SYNCHRONOUS) .and() .withExternal() .source(JOIN) .target(E)
验证逻辑
修改后,只有当L区域处于L2且R区域处于R2的同时,JOIN转换才会触发。按照你之前的事件顺序[TIK, TOK, FUZ],此时L区域在L1、R区域在R2,不满足同步条件,不会进入终态E;只有当你再次发送TIK让L区域回到L2,两个区域都处于目标状态时,才会触发JOIN并进入E。
自定义触发条件(可选)
如果需要更灵活的判断逻辑,还可以通过guard手动校验当前激活状态:
.and() .withJoin() .source(R2).source(L2) .target(JOIN) .guard(context -> { // 手动检查当前所有激活状态是否包含L2和R2 Set<String> activeStateIds = context.getStateMachine().getState().getIds(); return activeStateIds.contains("L2") && activeStateIds.contains("R2"); })
内容的提问来源于stack exchange,提问作者Wazi Armstrong
相关产品推荐
相关产品推荐

