看看什么是状态机

状态机

在我们日常开发中,我们提到的状态机基本都是有限状态机,用于解决状态相关的问题。有限状态机可以通过状态转换和事件触发来描述程序的行为和状态迁移。

一个状态机通常包含以下几个要素:

  1. 状态(States):代表系统可能处于的各种状态,例如 “已下单”、”已支付”、”已发货” 等。
  2. 事件(Events):触发状态转换的事件,例如 “下单”、”支付”、”发货” 等。
  3. 转换(Transitions):定义状态之间的转换规则,即在某个事件发生时,系统从一个状态转换到另一个状态的规则。
  4. 动作(Actions):在状态转换发生时执行的操作或行为。

状态机的实现,有很多种方式,可以用一些状态机的框架,如Spring StateMachine,也可以用状态模式,也可以自己封装一个工具类都行。

如果没有一个严格的状态机控制的话,我们是可以随便修改订单的状态的,我们可以在已下单状态直接推进到已发货状态,这显然是不对的。

而状态机就是来控制这个状态的流转的他的目的都是把状态、事件、转换以及动作封装在一起的,他把这些东西内聚在一起了。有了它,一个已下单状态的订单,只能通过支付事件来驱动,并且还会有一些其他的约束,比如支付金额>0(转移条件)等,然后他的下一个状态只能是已支付这样的。

Spring StateMachine

Spring State Machine(简称 Spring SM)是 Spring Framework 的一个模块,它提供了一个用于构建有限状态机的框架。

  • 获取任务状态,创建状态机

  • @Component
    public class WorkStateMachineFactory implements StateMachineFactory {
    
        @Resource
        private WorkStateMachineHandler stateMachineHandler;
    
        @Override
        public UntypedStateMachine createStateMachine(Object initialStateId) {
            UntypedStateMachineBuilder stateMachineBuilder = StateMachineBuilderFactory.create(WorkStateMachine.class);
            UntypedStateMachine stateMachine = stateMachineBuilder.newUntypedStateMachine(initialStateId, StateMachineConfiguration.create());
            //  添加监听器,开始处理,异常处理,完成处理
            stateMachine.addDeclarativeListener(stateMachineHandler);
            return stateMachine;
        }
    }
    //-----------------------------
    UntypedStateMachine workMachine =
         workStateMachineFactory.createStateMachine(WorkStatusEnum.valueOf(workStatus));
    workMachine.fire(MachineEventUtils.getWorkEventByReportStatus(workToStatus), reportContext);
    //状态改变
    @States({
            @State(name = WorkStateConstants.RUNNABLE, initialState = true),
            @State(name = WorkStateConstants.RUNNING),
            @State(name = WorkStateConstants.STOPPING),
            @State(name = WorkStateConstants.UNKNOWN),
            @State(name = WorkStateConstants.FAIL),
            @State(name = WorkStateConstants.STOPPED),
            @State(name = WorkStateConstants.FINISHED)
    })
    @Transitions({
            @Transit(from = WorkStateConstants.RUNNABLE, to = WorkStateConstants.FAIL, on = WorkEventConstants.IGNORE_GROUP,callMethod = "fromRunnableToFailByIgnoreGroup"),
            @Transit(from = WorkStateConstants.RUNNABLE, to = WorkStateConstants.RUNNING, on = WorkEventConstants.TAKE, callMethod = "fromRunnableToRunningByTake"),
            @Transit(from = WorkStateConstants.RUNNING, to = WorkStateConstants.RUNNING, on = WorkEventConstants.REPORT_RUNNING, callMethod = "fromRunningToRunningByReportRunning"),
    })
    @StateMachineParameters(stateType = WorkStatusEnum.class, eventType = WorkEventEnum.class, contextType = WorkContext.class)
    @Slf4j
    public class WorkStateMachine extends AbstractUntypedStateMachine {
    
        @Resource
        private IWorkService workService;
    
        /**
         * 运行->运行失败 上报失败
         */
        public void fromRunnableToFailByIgnoreGroup(WorkStatusEnum from, WorkStatusEnum to, WorkEventEnum event, WorkContext context) {
    
            workService.workIgnoreGroup(from,to,event,context);
    
        }
    }
    
  • tips:由于StateMachine实例不是由Spring容器创建,所以这个过程中无法通过注解方式开启事务(Spring没有机会去创建事务代理),如果需要事务,必须采用编程式事务,在AbstractStateMachineEngine的fire函数中隐式的实现。


看看什么是状态机
http://lzhnet.top/2023/07/15/看看什么是状态机/
Author
kuaile000
Posted on
July 15, 2023
Licensed under