Spring 状态机:公共转换

Spring state-machine: common transition

有没有办法为多个事件配置通用的外部转换? 即

  1. 对于取消事件上的所有状态 X、Y、Z -> 取消。 其中 X,Y,Z - 来源取消 - 目标状态
  2. 对于已取消状态 运行 公共 内部 转换 所有 事件

我有 20 多个状态要应用此转换,手动配置所有状态并不方便。

我正在使用 EnumStateMachineConfigurerAdapter@EnableStateMachineFactory 配置状态机,我的配置如下所示

@Configuration
@EnableStateMachineFactory
public class ContentOnlyStateMachineConfig extends EnumStateMachineConfigurerAdapter<TaskState, WorkflowEvent> {

private final Action<TaskState, WorkflowEvent> someAction;
private final Action<TaskState, WorkflowEvent> anotherAction;

@Autowired
public ContentOnlyStateMachineConfig(
        final Action<TaskState, WorkflowEvent> someAction,
        final Action<TaskState, WorkflowEvent> anotherAction) {
    this.someAction = someAction;
    this.anotherAction = anotherAction;
}




@Override
public void configure(final StateMachineStateConfigurer<TaskState, WorkflowEvent> states)
        throws Exception {

    states
            .withStates()
            .initial(TaskState.CONTENT)
            .end(TaskState.COMPLETE)
            .state(TaskState.CONTENT, someAction)
            .state(TaskState.COMPLETE, anotherAction);

}

@Override
public void configure(
        final StateMachineTransitionConfigurer<TaskState, WorkflowEvent> transitions)
        throws Exception {

    transitions
            .withExternal()
            .source(TaskState.CONTENT).target(TaskState.SOME_STATE)
            .event(WorkflowEvent.EXCEPTION)
            .and()
            .withExternal()
            .source(TaskState.EXCEPTION).target(TaskState.CANCELED)
            .event(WorkflowEvent.CANCEL)
            .and()
            .withExternal()
            .source(TaskState.SOME_STATE_2).target(TaskState.SOME_STATE_1)
            .event(WorkflowEvent.SOME_EVENT_3)
            .and()
            .withExternal()
            .source(TaskState.SOME_STATE).target(TaskState.SOME_STATE_2)
            .event(WorkflowEvent.SOME_EVENT_2)
            .and()
            .withExternal()
            .source(TaskState.SOME_STATE).target(TaskState.COMPLETE)
            .event(WorkflowEvent.ADMIN_ACCEPT)
            .and()
            .withExternal()
            .source(TaskState.SOME_STATE).target(TaskState.CONTENT)
            .event(WorkflowEvent.SOME_EVENT);
}
}

没有允许用户创建意大利面条的快捷方式 ;)。话虽如此,如果您在纸上绘制状态图后看起来像意大利面条而不是清晰的状态图,我认为您做错了什么。

将所有东西都放在一台机器上很容易造成这种状态爆炸乳清配置本身开始看起来难以理解。通常这是机器设计师需要开始考虑使用嵌套子状态的时刻。如果您有多个状态,其中相同的事件应该使机器进入相同的状态,那么您已经在这些状态中拥有共享功能。

将这些状态放入子状态将允许从它们的父状态转移到远方。这通常是机器如何完成工作的模型。

不支持开箱即用的方式来配置具有多个源和单个目标的转换。

需要明确地执行此操作。
例如:

@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {

    transitions.withExternal()
    // normal transitions configuration ..

    // common error transitions
    for (var state : EnumSet.of(States.A, States,B, States.C)) { 
        transitions.withExternal().source(state).target(States.ERROR).event(ERROR_EVENT);
    }
}

(无法使用 Stream.of(),因为 withExternal() 会引发已检查的异常。)