You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot配置多个Spring StateMachine时启动报Bean重复注册错误

问题成因

这个报错和两个状态机工厂之间的命名无关,冲突发生在配置类自身的bean注册阶段:

  • Spring会将所有@Configuration标注的类注册为容器bean,默认bean名称为类名首字母小写。你的订单状态机配置类名为OrderStateMachine,对应的默认bean名就是orderStateMachine。
  • 你在@EnableStateMachineFactory(name = "orderStateMachine")中,又给要生成的StateMachineFactory实例指定了完全相同的bean名。
  • Spring Boot 2.1+版本默认禁止bean定义覆盖,容器启动阶段扫描到两个同名bean的注册请求就会直接抛出启动失败错误,此时还没走到依赖注入环节,所以你写的@Qualifier注入逻辑根本没机会执行。

另外你的代码里还存在状态配置的参数类型/枚举引用错误,就算解决重名问题也会后续报错:

  • 订单状态机配置中,initial()和end()方法要求传入**状态枚举(OrderState)**类型参数,你误引用了OrderEvent事件枚举的值:ITEM_PICKED属于OrderEvent,ORDER_CONFIRMED属于OrderState,你写反了枚举类前缀。
  • 支付状态机配置存在完全相同的问题,initial()和end()误引用了PaymentEvent事件枚举值,不符合方法参数类型要求。
修复方案

按顺序修复以下问题即可:

  1. 解决bean重名冲突,二选一即可:
    • 方案一:重命名配置类,避免配置类默认bean名和工厂名冲突。比如将OrderStateMachine改名为OrderStateMachineConfig、PaymentStateMachine改名为PaymentStateMachineConfig,此时配置类默认bean名为orderStateMachineConfig、paymentStateMachineConfig,和你指定的工厂名不再冲突。
    • 方案二:给配置类显式指定bean名,无需修改类名。在@Configuration注解上显式指定value即可,示例:
      @Configuration("orderStateMachineConfig")
      @EnableStateMachineFactory(name = "orderStateMachine")
      public class OrderStateMachine extends EnumStateMachineConfigurerAdapter<OrderState, OrderEvent> {
          // 配置内容
      }
      
      支付状态机配置同理,给@Configuration指定独立的bean名即可。
  2. 修正状态配置的枚举引用错误:
    • 订单状态机配置中,initial()传入订单状态枚举的初始态,end()传入订单状态枚举的终态,示例:
      @Override
      public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
          states.withStates()
                  .initial(OrderState.ORDER_INITIATED)
                  .end(OrderState.ORDER_CONFIRMED)
                  .end(OrderState.ORDER_CANCELLED)
                  .states(EnumSet.allOf(OrderState.class));
      }
      
    • 支付状态机配置同理,initial()和end()都传入PaymentState类型的枚举值,示例:
      @Override
      public void configure(StateMachineStateConfigurer<PaymentState, PaymentEvent> states) throws Exception {
          states.withStates()
                  .initial(PaymentState.PAYMENT_INITIATED)
                  .end(PaymentState.PAYMENT_COLLECTED)
                  .end(PaymentState.PAYMENT_CANCELLED)
                  .states(EnumSet.allOf(PaymentState.class));
      }
      
  3. (可选)如果你不需要按名称获取工厂,其实可以省略@EnableStateMachineFactory的name属性,由于两个工厂的泛型参数不同,Spring可以直接按类型区分注入,不需要额外指定名称和@Qualifier。

内容的提问来源于stack exchange,提问作者Chandan Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:39:16