Spring StateMachine 是一个基于 Spring 框架的状态机实现,用于管理复杂的状态转换逻辑。以下是对其核心概念、配置方法及实际应用的详细说明:
一、核心概念
- 状态(State)
O 定义对象的生命周期阶段(如订单的 新建、待支付、已支付、取消)。
O 支持层次化状态(子状态)和并行状态(分叉/合并)。
- 事件(Event)
O 触发状态转换的动作(如 支付事件、取消事件)。
- 转换(Transition)
O 状态之间的流转规则,分为:
外部转换:状态变化并触发动作。
内部转换:状态不变,但触发动作。
4.守卫(Guard)
O 转换前的条件检查(如检查用户权限或订单金额)。
- 动作(Action)
O 状态转换时执行的业务逻辑(如发送通知、更新数据库)。
二、配置 Spring StateMachine
1. 依赖引入
xml
<dependency>
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-starter</artifactId>
<version>3.2.0</version>
</dependency>
2. 定义状态与事件
java
public enum States {
INITIAL, NEW, PAYMENT_PENDING, PAID, CANCELLED
}
public enum Events {
CREATE, PAY, CANCEL
}
3. 配置状态机
java
@Configuration
@EnableStateMachine
public class StateMachineConfig extends StateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
states
.withStates()
.initial(States.INITIAL)
.states(EnumSet.allOf(States.class));
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
transitions
.withExternal()
.source(States.INITIAL).target(States.NEW)
.event(Events.CREATE)
.and()
.withExternal()
.source(States.NEW).target(States.PAYMENT_PENDING)
.event(Events.PAY)
.guard(checkOrderAmountGuard()) // 守卫条件
.and()
.withExternal()
.source(States.PAYMENT_PENDING).target(States.PAID)
.action(paymentAction()); // 执行动作
}
@Bean
public Guard<States, Events> checkOrderAmountGuard() {
return context -> {
Order order = context.getExtendedState().get("order", Order.class);
return order.getAmount() > 0;
};
}
@Bean
public Action<States, Events> paymentAction() {
return context -> {
Order order = context.getExtendedState().get("order", Order.class);
paymentService.processPayment(order);
};
}
}
三、使用状态机
1. 注入状态机并触发事件
java
@Service
public class OrderService {
@Autowired
private StateMachine<States, Events> stateMachine;
public void createOrder(Order order) {
stateMachine.getExtendedState().getVariables().put("order", order);
stateMachine.sendEvent(Events.CREATE);
}
public void payOrder(Order order) {
stateMachine.sendEvent(Events.PAY);
}
}
2. 监听状态变化
java
@Configuration
public class StateMachineListenerConfig {
@Bean
public StateMachineListener<States, Events> listener() {
return new StateMachineListenerAdapter<>() {
@Override
public void stateChanged(State<States, Events> from, State<States, Events> to) {
System.out.println("状态变更: " + from + " -> " + to);
}
};
}
}
四、高级功能
- 持久化状态
O 使用 StateMachinePersister 将状态保存到数据库或 Redis。
java
@Autowired
private StateMachinePersister<States, Events, String> persister;
public void persist(String orderId) {
persister.persist(stateMachine, orderId);
}
- 分布式支持
O 结合消息队列(如 RabbitMQ)实现跨服务的状态同步。
- 测试
O 使用 StateMachineTestPlan 验证状态转换逻辑。
java
@Test
public void testStateTransition() {
StateMachineTestPlan<States, Events> plan =
StateMachineTestPlanBuilder.<States, Events>builder()
.defaultAwaitTime(2)
.stateMachine(stateMachine)
.step().expectState(States.INITIAL).and()
.step().sendEvent(Events.CREATE).expectState(States.NEW).and()
.build();
plan.test();
}
五、典型应用场景
- 订单流程管理
O 处理订单状态的流转(创建、支付、发货、退款)。
- 审批工作流
O 定义多级审批的状态跳转(提交、审核、通过/驳回)。
- 游戏状态控制
O 管理游戏角色的行为状态(空闲、攻击、防御、死亡)。
六、常见问题
- 问题1:事件未触发转换
检查守卫条件是否返回 true,或事件是否绑定到正确的源状态。 - 问题2:状态机线程安全
确保每个状态机实例仅被单个线程使用,或在并发场景中正确同步。 - 问题3:持久化恢复失败
验证序列化/反序列化逻辑,确保存储的上下文数据完整。
通过以上步骤,可以高效利用 Spring StateMachine 管理复杂状态逻辑,减少硬编码的条件判断,提升代码可维护性。更多细节可参考 官方文档。