当前位置: 首页 > news >正文

spring状态机(不太优雅)笔记

文章目录

        • 什么是状态机
      • 事件、动作、业务的区别
      • 普通逻辑和状态机的区别
    • 集成及使用
      • 引入maven依赖
        • 定义状态枚举
        • 定义事件枚举
      • 初始化订单的状态集合以及状态转移事件
        • 状态转移的监听器
        • 测试

听到这个名词一愣,但是很快反应过来了,就是状态和逻辑控制名词化了。

当然,和普通逻辑相比,可不是改个名字而已,有很多不同。

什么是状态机

Java状态机是一种用于描述系统状态转换的模型,通过定义状态、事件、动作和转换规则来控制程序行为。

其核心要素如下:
**状态(States):**系统可能处于的固定状态,如订单状态中的"已支付"、“已发货"等 。 ‌
**事件(Events):**触发状态转换的外部或内部信号,如"支付”、“取消"等操作 。 ‌
**动作(Actions):**状态转换时执行的操作,例如更新状态字段或记录日志 。 ‌
**转换(Transitions):**定义事件触发下状态转移的规则,例如"支付成功"事件将"待支付"状态转为"支付成功”。

这么看是否还得维护个状态表,看起来才比较清楚。

事件、动作、业务的区别

这几个概念容易混淆。
事件:表示触发。
动作:要做的操作:
业务:包含(事件+动作),当然也可能有其他操作。

普通逻辑和状态机的区别

名称普通逻辑状态机
逻辑清晰度需要if else来实现逻辑判断,可读性差状态机通过预定义状态和事件,将状态转换规则显式化,避免冗余的条件判断,可读性强。
扩展性需要在原代码上修改逻辑,易出错,扩展性差。新增状态或事件时,只需扩展状态机配置,无需修改现有代码。
线程安全支持需手动处理同步问题(如使用synchronized或Lock),实现复杂且易出错。状态机框架(如Spring StateMachine)内置线程同步机制,确保并发场景下状态一致性。
业务解耦状态处理常耦合在业务方法内,难以独立测试。 ‌状态机将状态逻辑与业务代码分离,便于测试和复用。
可视化配置普通逻辑需通过代码硬编码状态转换,可读性差。 ‌框架支持通过代码或配置文件定义状态机,直观展示状态迁移路径。

集成及使用

引入maven依赖

<dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-core</artifactId><version>2.0.0.RELEASE</version></dependency><!-- uml to code --><dependency><groupId>org.springframework.statemachine</groupId><artifactId>spring-statemachine-uml</artifactId><version>2.0.0.RELEASE</version></dependency>
定义状态枚举

代码:

publicenumStates{UNPAID,// 待支付WAITING_FOR_RECEIVE,// 待收货DONE// 结束}
定义事件枚举

代码:

publicenumEvents{PAY,// 支付RECEIVE// 收货}

初始化订单的状态集合以及状态转移事件

代码:

publicclassStateMachineConfigextendsEnumStateMachineConfigurerAdapter<States,Events>{privateLoggerLOGGER=LoggerFactory.getLogger(getClass());@Overridepublicvoidconfigure(StateMachineStateConfigurer<States,Events>states)throwsException{states.withStates().initial(States.UNPAID).states(EnumSet.allOf(States.class));}@Overridepublicvoidconfigure(StateMachineTransitionConfigurer<States,Events>transitions)throwsException{transitions.withExternal().source(States.UNPAID).target(States.WAITING_FOR_RECEIVE).event(Events.PAY).and().withExternal().source(States.WAITING_FOR_RECEIVE).target(States.DONE).event(Events.RECEIVE);}//守护@BeanpublicGuard<States,Events>guard(){returnnewGuard<States,Events>(){publicbooleanevaluate(StateContext<States,Events>context){returntrue;}};}
状态转移的监听器
@WithStateMachinepublicclassEventListener{privateLoggerLOGGER=LoggerFactory.getLogger(getClass());@OnTransition(target="UNPAID")publicvoidcreate(){//此处可以执行具体业务逻辑处理LOGGER.info("--------------------订单创建,待支付-----------------------");}@OnTransition(source="UNPAID",target="WAITING_FOR_RECEIVE")publicvoidpay(){//此处可以执行具体业务逻辑处理LOGGER.info("--------------------用户完成支付,待收货--------------------");}@OnTransition(source="WAITING_FOR_RECEIVE",target="DONE")publicvoidreceive(){//此处可以执行具体业务逻辑处理LOGGER.info("--------------------用户已收货,订单完成----------------------");}}
测试

测试类代码:

@RunWith(SpringRunner.class)@SpringBootTestpublicclassApplicationTests{@TestpublicvoidcontextLoads(){}@AutowiredprivateStateMachine<States,Events>stateMachine;@Testpublicvoidtest()throwsException{stateMachine.start();stateMachine.sendEvent(Events.PAY);stateMachine.sendEvent(Events.RECEIVE);}}

1.只运行启动

@Testpublicvoidtest()throwsException{stateMachine.start();//springboot启动时开启 待支付//stateMachine.sendEvent(Events.PAY); //支付操作 待收货//stateMachine.sendEvent(Events.RECEIVE); //收货操作 结束}

2.运行启动与支付操作

@Testpublicvoidtest()throwsException{stateMachine.start();//springboot启动时开启 待支付//stateMachine.sendEvent(Events.PAY); //支付操作 待收货//stateMachine.sendEvent(Events.RECEIVE); //收货操作 结束}

3.全部执行

@Testpublicvoidtest()throwsException{stateMachine.start();//springboot启动时开启 待支付stateMachine.sendEvent(Events.PAY);//支付操作 待收货stateMachine.sendEvent(Events.RECEIVE);//收货操作 结束}
http://www.jsqmd.com/news/1212162/

相关文章:

  • Fief未来展望:下一代用户认证管理系统的发展方向 [特殊字符]
  • SI4735库数字音频输出教程:I2S接口配置与优化
  • 未来展望:live框架路线图与Web实时技术发展趋势分析
  • 2026实用指南:号易号卡正规推荐码选择及全套使用攻略 - 号易邀请码08888
  • Gemini CLI:开发者夺回模型调用权的协议级工具
  • 深度解析猫抓Cat-Catch:浏览器资源嗅探扩展的3大核心技术实现原理与性能优化
  • Sqribble:面向业务人员的文档操作系统与确定性排版实践
  • SI4735库多显示支持:LCD、OLED、TFT屏幕适配指南
  • 终极指南:3步轻松重置JetBrains IDE试用期,告别30天限制焦虑
  • 嵌入式USB FIFO缓存机制:单包与双包配置实战解析
  • CardKit错误处理与调试:解决常见图像渲染问题的实用技巧
  • 基于DeepSeek和Dify的智能客服系统架构设计与实践
  • 2026湖州彩钢瓦修缮哪家靠谱?本地滨湖厂房金属屋面防水翻新四大品牌测评|太湖高湿工况专属指南 - 本地便民网
  • C++性能优化:__builtin_expect分支预测原理与实战指南
  • Dify平台:低代码开发大模型应用的最佳实践
  • 剑网1武林联赛120级技能机制与实战平衡性深度解析
  • AI算力基建动态简报(2026.07.18)
  • poissonsearch-py搜索查询指南:构建复杂Elasticsearch查询的Python实现
  • 高校AI黑客松的技术实践与工程挑战
  • React组件通信:原理、实践与性能优化
  • 安川机器人外部伺服轴配置与优化指南
  • Guns项目数据库设计指南:10个核心模块表结构详解
  • MOSFET温度估算原理与工程实践指南
  • UnityExplorer运行时调试器:原理、部署与实战调试指南
  • 反思日记:提升元认知能力的结构化写作方法
  • openGauss备节点WAL同步问题诊断与修复
  • 三大AI模型技术解析:Gemini 3.5 Pro、GPT-5.6与Watermelon对比实战
  • HyperCube未来路线图:元宇宙和AI基础设施的终极愿景
  • 网络端口测试原理与工具实战指南
  • @nuxt/components 深度解析:为什么它是Nuxt开发者必备的组件管理神器