
肖哥弹架构 跟大家“弹弹” Spring Statemachine设计与实战应用,需要代码关注
欢迎 点赞,关注,转发。
关注公号Solomon肖哥弹架构获取更多精彩内容
历史热点文章
- MyCat应用实战:分布式数据库中间件的实践与优化(篇幅一)
- 图解深度剖析:MyCat 架构设计与组件协同 (篇幅二)
- 一个项目代码讲清楚DO/PO/BO/AO/E/DTO/DAO/ POJO/VO
- 写代码总被Dis:5个项目案例带你掌握SOLID技巧,代码有架构风格
- 里氏替换原则在金融交易系统中的实践,再不懂你咬我
本文探讨Spring Statemachine的高级功能,涵盖状态机服务、拦截器、监听器、错误处理及持久化等核心模块。主要内容包括:
- 状态机服务:通过缓存和对象池优化实例管理,解决资源隔离与并发控制问题;
- 拦截器与监听器:对比两者的差异,实现流程控制、审计日志和安全校验;
- 错误处理机制:提供全局监听、异常处理器等方案,保障状态一致性;
- 持久化实践:自定义存储库支持Redis、加密存储等场景,详解
StateMachinePersist与StateMachineRuntimePersister的协作。
1. 状态机服务(StateMachineService)

状态机服务是对Spring Statemachine核心功能的高层抽象封装,提供统一的状态机生命周期管理和访问控制。它作为应用层与状态机框架之间的中间层,简化状态机的使用复杂度。
1.1 状态机服务的核心职责
- 生命周期管理:统一管理状态机的创建、启动、停止和销毁
- 实例存取控制:提供状态机实例的获取和释放机制
- 资源隔离:确保不同业务场景使用独立的状态机实例
- 性能优化:通过缓存/池化技术减少重复创建开销
1.2 解决的关键问题
| 问题类型 | 传统方式痛点 | 状态机服务方案 |
|---|---|---|
| 实例管理混乱 | 直接使用StateMachineFactory导致实例散落各处 | 集中式存储管理 |
| 资源泄漏风险 | 需手动调用stop()释放资源 | 提供release自动清理 |
| 并发访问冲突 | 多线程共享同一状态机实例 | 线程隔离或同步控制 |
| 配置一致性 | 每次getStateMachine()可能返回新实例 | 保证配置相同的机器ID返回同一实例 |
1.3 服务设计实现方案
1.3.1 基础版本(带简单缓存)
/**
* 状态机服务实现(基于缓存机制)
*
* 核心职责:
* 1. 统一管理状态机实例的生命周期
* 2. 提供线程安全的状态机存取
* 3. 避免重复创建相同配置的状态机
*
* 设计特点:
* - 使用ConcurrentHashMap实现线程安全缓存
* - 通过@Transactional支持事务边界
* - 实现PreDestroy确保资源清理
*/
@Service
public class StateMachineServiceImpl implements StateMachineService {
// 注入状态机工厂(由Spring自动配置)
@Autowired
private StateMachineFactory<String, String> factory;
// 状态机实例缓存(Key: machineId, Value: 状态机实例)
private final Map<String, StateMachine<String, String>> machineCache =
new ConcurrentHashMap<>();
/**
* 获取状态机实例(缓存优先)
*
* @param machineId 状态机唯一标识
* @return 已初始化的状态机实例
*
* @Transactional注解确保:
* 1. 方法执行在事务上下文中
* 2. 状态机操作可参与事务(需配合持久化配置)
*/
@Override
@Transactional
public StateMachine<String, String> getMachine(String machineId) {
return machineCache.computeIfAbsent(machineId, id -> {
// 缓存未命中时创建新实例
StateMachine<String, String> machine = factory.getStateMachine(id);
// 启动状态机(触发初始状态转换)
machine.start();
// 将新实例放入缓存
return machine;
});
}
/**
* 释放状态机资源
*
* @param machineId 要释放的状态机ID
*
* 注意:
* - 必须显式调用以避免内存泄漏
* - 典型场景:业务流程结束时调用
*/
@Override
public void releaseMachine(String machineId) {
StateMachine<String, String> machine = machineCache.remove(machineId);
if (machine != null && machine.isRunning()) {
// 停止状态机(释放内部资源)
machine.stop();
}
}
/**
* 容器销毁前的清理钩子
*
* 确保:
* 1. 所有状态机实例被正确停止
* 2. 缓存清空帮助GC回收
*/
@PreDestroy
public void destroy() {
machineCache.values().forEach(machine -> {
if (machine.isRunning()) {
machine.stop();
}
});
machineCache.clear();
}
// ---- 可选增强功能 ----
/**
* 获取当前缓存状态(监控用)
*/
public Map<String, String> getCacheStatus() {
Map<String, String> status = new HashMap<>();
machineCache.forEach((id, machine) -> {
status.put(id, machine.getState().toString());
});
return status;
}
}
1.3.2 高级版本(带对象池)
/**
* 基于对象池的状态机服务实现
*
* 核心功能:
* 1. 管理状态机实例的生命周期(创建/销毁)
* 2. 通过对象池复用状态机实例,降低创建开销
* 3. 提供线程安全的状态机存取服务
*
* 适用场景:
* - 高频使用状态机的并发环境
* - 需要严格控制资源占用的场景
*/
@Service
public class PooledStateMachineService {
// 使用Apache Commons Pool2实现的对象池
private final GenericObjectPool<StateMachine<String, String>> pool;
/**
* 构造函数(依赖注入StateMachineFactory)
*
* @param factory 状态机工厂,用于创建新的状态机实例
*/
public PooledStateMachineService(StateMachineFactory

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



