密封类通过限定状态子类集合并配合显式流转校验,协同编译期约束与运行期检查防范中间态逃逸:定义final状态类、禁用外部继承、强制switch校验转移路径、集成Saga补偿机制,并辅以反序列化防护和审计日志。

密封类(Sealed Class)本身是 Java 17+ 的语言特性,用于限制继承关系,它不能直接“限制状态流转区间”或“防范中间态逃逸”——这类问题本质属于业务逻辑与状态机设计范畴,而非类型系统能自动约束的运行时行为。真正起作用的是:用密封类建模**有限且明确的状态集合**,再配合状态转移规则校验,才能在编译期和运行期协同拦截非法流转。
用密封类定义状态枚举空间
先将所有可能的、被允许的事务状态声明为密封类的子类,禁止外部新增任意状态:
-
每个状态是 final 的具体类(如
OrderCreated、PaymentSucceeded、InventoryDeducted),不可被继承或伪造; - 状态类不暴露 public 构造器,仅通过工厂方法或事件驱动创建,避免随意构造中间态实例;
-
状态类可携带上下文字段(如订单ID、时间戳、补偿标记),但字段设为
final,确保状态不可变。
在状态转移函数中强制校验合法路径
密封类只管“有哪些状态”,不管“怎么跳”。必须在状态变更入口(如 apply(Event event))中显式编码流转规则:
- 用
switch按当前状态 + 事件类型分支,每个 case 明确写出允许的目标状态(例如:case OrderCreated e -> new PaymentSucceeded(...)); - 未覆盖的组合默认抛出
IllegalStateException,而不是静默忽略或 fallback; - 避免使用字符串或 int 表示状态码——它们无法被编译器检查,容易绕过校验。
结合 Saga 补偿机制封堵“半成功”中间态
分布式事务中的“中间态逃逸”往往发生在某个分支成功、其他分支失败后,系统卡在非终态(如订单已建、库存未扣)。此时密封类需支持:
- 每个状态类实现
isTerminal()和requiresCompensation()方法,让协调器清楚哪些状态必须回滚; - 引入
Compensated或FailedWithCompensation等补偿完成态,作为合法终态之一,而非仅靠Succeed/Fail二元判断; - 状态机引擎在执行前检查:当前状态是否允许接收该事件(例如
InventoryDeducted不应再接收PayEvent),否则拒绝处理。
配套措施:防止运行时绕过类型安全
密封类防不住反射、序列化或 JSON 反解析构造非法状态。需补充:
- 自定义
ObjectMapper反序列化器,只允许注册过的密封子类; - 在反序列化后调用
validateTransition(from, to)做二次校验; - 关键状态变更记录审计日志,并与 Saga 状态机日志对齐,便于事后追溯逃逸路径。

















