Spring高级开发:状态机/事件/插件

Spring 状态机与事件机制插件开发示例

我将为您演示一个完整的 Spring 状态机实现,包含状态机配置、事件机制和可扩展的插件体系。以下是一个订单处理系统的示例:

1. 添加依赖(pom.xml)

xml 复制代码
<dependencies>
    <!-- Spring State Machine -->
    <dependency>
        <groupId>org.springframework.statemachine</groupId>
        <artifactId>spring-statemachine-starter</artifactId>
        <version>4.2.0</version>
    </dependency>
    
    <!-- Spring Event 相关 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>6.0.9</version>
    </dependency>
</dependencies>

2. 定义核心接口和类

2.1 状态和事件枚举

java 复制代码
// 状态枚举
public enum OrderState {
    NEW, 
    PAYMENT_PENDING, 
    PAID, 
    SHIPPED, 
    DELIVERED, 
    CANCELLED
}

// 事件枚举
public enum OrderEvent {
    CREATE_ORDER, 
    INITIATE_PAYMENT, 
    PAYMENT_COMPLETED, 
    SHIP_ORDER, 
    DELIVERY_CONFIRMED, 
    CANCEL_ORDER
}

2.2 插件接口定义

java 复制代码
// 状态变更监听器接口
public interface StateChangeListener {
    void onStateChange(OrderState from, OrderState to, String orderId);
}

// 订单操作插件接口
public interface OrderOperationPlugin {
    void execute(String orderId, OrderState currentState);
}

// 插件管理器接口
public interface PluginManager {
    void registerStateChangeListener(StateChangeListener listener);
    void notifyStateChange(OrderState from, OrderState to, String orderId);
    void executePlugins(String orderId, OrderState currentState);
}

3. 实现状态机配置

java 复制代码
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> {

    @Autowired
    private List<OrderOperationPlugin> plugins;

    @Override
    public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
        states
            .withStates()
            .initial(OrderState.NEW)
            .state(OrderState.PAYMENT_PENDING)
            .junction(OrderState.PAID)
            .end(OrderState.DELIVERED)
            .end(OrderState.CANCELLED)
            .fork(OrderState.SHIPPED);
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
        transitions
            .withExternal()
                .source(OrderState.NEW).target(OrderState.PAYMENT_PENDING)
                .event(OrderEvent.CREATE_ORDER)
                
            .and().withExternal()
                .source(OrderState.PAYMENT_PENDING).target(OrderState.PAID)
                .event(OrderEvent.INITIATE_PAYMENT)
                
            .and().withExternal()
                .source(OrderState.PAID).target(OrderState.SHIPPED)
                .event(OrderEvent.SHIP_ORDER)
                
            .and().withExternal()
                .source(OrderState.SHIPPED).target(OrderState.DELIVERED)
                .event(OrderEvent.DELIVERY_CONFIRMED)
                
            .and().withExternal()
                .source(OrderState.NEW).target(OrderState.CANCELLED)
                .event(OrderEvent.CANCEL_ORDER)
                
            .and().withExternal()
                .source(OrderState.PAYMENT_PENDING).target(OrderState.CANCELLED)
                .event(OrderEvent.CANCEL_ORDER);
    }
    
    @Bean
    public PluginManager pluginManager() {
        return new DefaultPluginManager(plugins);
    }
}

4. 插件实现

4.1 默认插件管理器

java 复制代码
@Component
public class DefaultPluginManager implements PluginManager {
    private final List<StateChangeListener> stateChangeListeners = new ArrayList<>();
    private final List<OrderOperationPlugin> operationPlugins;

    public DefaultPluginManager(List<OrderOperationPlugin> plugins) {
        this.operationPlugins = plugins;
    }

    @Override
    public void registerStateChangeListener(StateChangeListener listener) {
        stateChangeListeners.add(listener);
    }

    @Override
    public void notifyStateChange(OrderState from, OrderState to, String orderId) {
        stateChangeListeners.forEach(listener -> listener.onStateChange(from, to, orderId));
    }

    @Override
    public void executePlugins(String orderId, OrderState currentState) {
        operationPlugins.forEach(plugin -> plugin.execute(orderId, currentState));
    }
}

4.2 示例插件实现

java 复制代码
// 日志记录插件
@Component
public class LoggingPlugin implements OrderOperationPlugin {
    @Override
    public void execute(String orderId, OrderState currentState) {
        System.out.println("订单 " + orderId + " 当前状态: " + currentState + " - 正在记录日志");
    }
}

// 邮件通知插件
@Component
public class EmailNotificationPlugin implements OrderOperationPlugin {
    @Override
    public void execute(String orderId, OrderState currentState) {
        System.out.println("订单 " + orderId + " 当前状态: " + currentState + " - 发送邮件通知");
    }
}

// 库存管理插件
@Component
public class InventoryUpdatePlugin implements OrderOperationPlugin {
    @Override
    public void execute(String orderId, OrderState currentState) {
        if (currentState == OrderState.PAID) {
            System.out.println("订单 " + orderId + " 已支付,正在更新库存");
        }
    }
}

5. 状态监听器实现

java 复制代码
@Component
public class AuditStateChangeListener implements StateChangeListener {
    @Override
    public void onStateChange(OrderState from, OrderState to, String orderId) {
        System.out.println("订单状态变更: " + orderId + " 从 " + from + " 到 " + to + " - 审计记录已创建");
    }
}

6. 服务层实现

java 复制代码
@Service
public class OrderService {

    @Autowired
    private StateMachine<OrderState, OrderEvent> stateMachine;

    @Autowired
    private PluginManager pluginManager;

    public OrderService() {
        // 注册监听器
        pluginManager.registerStateChangeListener(new AuditStateChangeListener());
    }

    public void handleOrderEvent(String orderId, OrderEvent event) {
        try {
            stateMachine.start();
            OrderState currentState = stateMachine.getState().getId();
            
            // 发送事件
            stateMachine.sendEvent(event);
            
            OrderState newState = stateMachine.getState().getId();
            
            // 触发状态变更监听器
            if (currentState != newState) {
                pluginManager.notifyStateChange(currentState, newState, orderId);
            }
            
            // 执行操作插件
            pluginManager.executePlugins(orderId, newState);
            
        } catch (Exception e) {
            System.err.println("处理订单事件失败: " + e.getMessage());
        } finally {
            stateMachine.stop();
        }
    }
}

7. 控制器示例

java 复制代码
@RestController
@RequestMapping("/orders")
public class OrderController {

    @Autowired
    private OrderService orderService;

    @PostMapping("/{orderId}/events")
    public ResponseEntity<String> sendEvent(@PathVariable String orderId, @RequestParam String event) {
        try {
            OrderEvent orderEvent = OrderEvent.valueOf(event.toUpperCase());
            orderService.handleOrderEvent(orderId, orderEvent);
            return ResponseEntity.ok("事件已处理: " + event);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body("无效的事件类型: " + event);
        }
    }
    
    @GetMapping("/{orderId}/status")
    public ResponseEntity<String> checkStatus(@PathVariable String orderId) {
        // 这里应该从存储中获取当前状态,为简化示例返回固定值
        return ResponseEntity.ok("订单 " + orderId + " 当前状态: 示例状态");
    }
}

8. 可扩展性说明

如何添加新插件:

java 复制代码
@Component
public class NewFeaturePlugin implements OrderOperationPlugin {
    @Override
    public void execute(String orderId, OrderState currentState) {
        // 新功能逻辑
    }
}

如何添加新状态监听器:

java 复制代码
@Component
public class NewStateChangeListener implements StateChangeListener {
    @Override
    public void onStateChange(OrderState from, OrderState to, String orderId) {
        // 新监听器逻辑
    }
}

使用示例:

shell 复制代码
# 创建订单
POST /orders/123/events?event=CREATE_ORDER

# 发起支付
POST /orders/123/events?event=INITIATE_PAYMENT

# 发货
POST /orders/123/events?event=SHIP_ORDER

# 确认送达
POST /orders/123/events?event=DELIVERY_CONFIRMED

# 取消订单
POST /orders/123/events?event=CANCEL_ORDER

这个实现具有以下特点:

  1. 灵活的状态机配置:使用 Spring StateMachine 配置订单状态流转
  2. 可扩展的插件系统:通过接口设计支持轻松添加新插件
  3. 事件驱动架构:利用状态变更事件触发相关业务逻辑
  4. 良好的分离关注点:核心状态机逻辑与业务插件解耦
  5. 易于维护和测试:各组件之间通过接口通信,便于单元测试和替换实现

您可以根据具体业务需求扩展更多状态、事件和插件功能。

相关推荐
Mr Aokey1 小时前
Spring MVC参数绑定终极手册:单&多参/对象/集合/JSON/文件上传精讲
java·后端·spring
地藏Kelvin2 小时前
Spring Ai 从Demo到搭建套壳项目(二)实现deepseek+MCP client让高德生成昆明游玩4天攻略
人工智能·spring boot·后端
菠萝012 小时前
共识算法Raft系列(1)——什么是Raft?
c++·后端·算法·区块链·共识算法
长勺2 小时前
Spring中@Primary注解的作用与使用
java·后端·spring
小奏技术3 小时前
基于 Spring AI 和 MCP:用自然语言查询 RocketMQ 消息
后端·aigc·mcp
编程轨迹3 小时前
面试官:如何在 Java 中读取和解析 JSON 文件
后端
lanfufu3 小时前
记一次诡异的线上异常赋值排查:代码没错,结果不对
java·jvm·后端
编程轨迹4 小时前
如何在 Java 中实现 PDF 与 TIFF 格式互转
后端
编程轨迹4 小时前
面试官:你知道如何在 Java 中创建对话框吗
后端
编程轨迹4 小时前
深入理解 Java 中的信号机制
后端