【问题标题】:Spring state machine bean detection not workingSpring状态机bean检测不起作用
【发布时间】:2018-06-13 18:01:45
【问题描述】:

我目前正在使用 Spring 状态机构建一个小示例项目。

我的配置:

@Configuration
@EnableStateMachine
public class StateMachineConfiguration extends EnumStateMachineConfigurerAdapter<States, Events> {

    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states)
            throws Exception {
        states
                .withStates()
                .initial(States.LOCKED)
                .states(EnumSet.allOf(States.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
            throws Exception {
        transitions
                .withExternal()
                .source(States.LOCKED)
                .target(States.UNLOCKED)
                .event(Events.COIN)
                .and()
                .withExternal()
                .source(States.UNLOCKED)
                .target(States.LOCKED)
                .event(Events.PUSH);
    }

    @Bean
    public StateMachineListener<States, Events> listener() {
        return new StateMachineListenerAdapter<States, Events>() {
            @Override
            public void stateChanged(State<States, Events> from, State<States, Events> to) {
                System.out.println("State change to " + to.getId());
            }
        };
    }
}

当我现在尝试用

注入状态机时
@Autowired
StateMachine<States, Events> stateMachine;

IntelliJ 给了我提示,这不能是 autowired 因为那里没有 bean。如果我运行应用程序,我也会遇到异常。

gradle 依赖:

compile 'org.springframework.statemachine:spring-statemachine-core:2.0.1.
compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: '2.0.1.RELEASE'
compile group: 'org.springframework.shell', name: 'spring-shell-starter', version: '2.0.1.RELEASE'
compile group: 'org.springframework.statemachine', name: 'spring-statemachine-boot', version: '1.2.11.RELEASE'

【问题讨论】:

  • 问题解决了吗?
  • @seanhawk 查看我的帖子
  • @DanielEisenreich 在代码中,如果您从 @EnableStateMachine 更改为 @EnableStateMachineFactory 注释,那将有效。谢谢。

标签: java spring spring-boot spring-statemachine


【解决方案1】:

我不知道问题出在哪里。但是下面的 sn-p 对我有用。

@Configuration
@EnableStateMachine
public class StateMachineConfiguration {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Bean
    public StateMachine<States, Events> stateMachine(StateMachineListener<States, Events> listener) throws Exception {
        StateMachineBuilder.Builder<States, Events> builder = StateMachineBuilder.builder();

        builder.configureStates()
            .withStates()
            .initial(States.LOCKED)
            .states(EnumSet.allOf(States.class));

        builder.configureTransitions()
            .withExternal()
            .source(States.LOCKED)
            .target(States.UNLOCKED)
            .event(Events.COIN)
            .and()
            .withExternal()
            .source(States.UNLOCKED)
            .target(States.LOCKED)
            .event(Events.PUSH);

        StateMachine<States, Events> stateMachine = builder.build();
        stateMachine.addStateListener(listener);
        return stateMachine;
    }

    @Bean
    public StateMachineListener<States, Events> listener() {
        return new StateMachineListenerAdapter<States, Events>() {
            @Override
            public void stateChanged(State<States, Events> from, State<States, Events> to) {
                logger.info("State change to " + to.getId());
            }
        };
    }
}

【讨论】:

  • sn-p 有效,因为您正在自己创建 StateMachine @Bean。 Intellij 可以找到它。也就是说,如果 StateMachine 是@Autowired,Spring 将自动实例化一个默认的 StateMachine bean,如果一个没有定义为 @Bean。归功于@guidadic,但他还不能评论其他用户的帖子。
  • 另外,您可能会遇到此错误:The bean 'stateMachine' could not be registered. A bean with that name has already been defined in class path resource [com/tests/springboottests/stateMachine/StateMachineConfig.class] and overriding is disabled. 解决方案:spring.main.allow-bean-definition-overriding=true in application.properties
【解决方案2】:

你可以试试

@EnableStateMachine(name = "myStateMachine")

@Autowired
StateMachine<States, Events> myStateMachine;

【讨论】:

    【解决方案3】:

    我也有同样的问题。

    我做到了。

    它正在工作

    @SpringBootApplication
    @EnableStateMachine
    public class StateMachineSpringBootApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(StateMachineSpringBootApplication.class, args);
        }
    
    }
    

    配置

    @Configuration
    public class MachineConfigurationCustom extends EnumStateMachineConfigurerAdapter<BookStates, BookEvents> {
    
        @Bean
        public StateMachine<BookStates, BookEvents> stateMachine(StateMachineListener<BookStates, BookEvents> listener) throws Exception {
    
            StateMachineBuilder.Builder<BookStates, BookEvents>  builder =
                    StateMachineBuilder.builder();
    
            builder.configureStates()
                    .withStates()
                    .initial(BookStates.AVAILABLE)
                    .states(EnumSet.allOf(BookStates.class));
    
            builder.configureTransitions()
                    .withExternal()
                    .source(BookStates.AVAILABLE)
                    .target(BookStates.BORROWED)
                    .event(BookEvents.BORROW)
                    .and()
                    .withExternal()
                    .source(BookStates.BORROWED)
                    .target(BookStates.AVAILABLE)
                    .event(BookEvents.RETURN)
                    .and()
                    .withExternal()
                    .source(BookStates.AVAILABLE)
                    .target(BookStates.IN_REPAIR)
                    .event(BookEvents.START_REPAIR)
                    .and()
                    .withExternal()
                    .source(BookStates.IN_REPAIR)
                    .target(BookStates.AVAILABLE)
                    .event(BookEvents.END_REPAIR);
    
            StateMachine<BookStates, BookEvents> stateMachine = builder.build();
            stateMachine.addStateListener(listener);
            return stateMachine;
        }
    
        @Override
        public void configure(StateMachineConfigurationConfigurer<BookStates, BookEvents> config) throws Exception {
            config.withConfiguration()
                    .autoStartup(true)
                    .listener(new LoggingMachineListener());
        }
    
    
    }
    

    听众

    @Component
    public class LoggingMachineListener implements StateMachineListener<BookStates, BookEvents> {
        private static final Logger LOGGER = LoggingUtils.LOGGER;
    
        @Override
        public void stateChanged(State<BookStates, BookEvents> from, State<BookStates, BookEvents> to) {
            LOGGER.info("State changed from {} to {}", getStateInfo(from), getStateInfo(to));
        }
    
        @Override
        public void stateEntered(State<BookStates, BookEvents> state) {
            LOGGER.info("Entered state {}", getStateInfo(state));
        }
    
        @Override
        public void stateExited(State<BookStates, BookEvents> state) {
            LOGGER.info("Exited state {}", getStateInfo(state));
        }
    
        @Override
        public void stateMachineStarted(StateMachine<BookStates, BookEvents> stateMachine) {
            LOGGER.info("Machine started: {}", stateMachine);
        }
    
        @Override
        public void stateMachineStopped(StateMachine<BookStates, BookEvents> stateMachine) {
            LOGGER.info("Machine stopped: {}", stateMachine);
        }
    
        @Override
        public void stateMachineError(StateMachine<BookStates, BookEvents> stateMachine, Exception exception) {
            LOGGER.error("Machine error: {}", stateMachine);
        }
    
        @Override
        public void extendedStateChanged(Object key, Object value) {
            LOGGER.info("Extended state changed: [{}: {}]", key, value);
        }
    
    ......
    }
    

    跑步者

    @Component
    public class RunnerStateMachineWithCommandLine implements CommandLineRunner {
    
        private final StateMachine<BookStates, BookEvents> stateMachine;
    
        @Autowired
        public RunnerStateMachineWithCommandLine(StateMachine<BookStates, BookEvents> stateMachine) {
            this.stateMachine = stateMachine;
        }
    
        @Override
        public void run(String... args){
            stateMachine.start();
            stateMachine.sendEvent(BookEvents.RETURN);
            stateMachine.sendEvent(BookEvents.BORROW);
            stateMachine.stop();
        }
    }
    

    【讨论】:

    • 我提供了解决方案。它正在工作。但是为什么我需要明确定义 @Bean public State Machine 呢?可能有人知道为什么会这样吗?
    • 有很多例子没有使用这种方法,而是注释就足够了@EnableStateMachine。
    【解决方案4】:

    在配置类中,添加注解@EnableStateMachineFactory即可,

    @EnableStateMachineFactory
    @Configuration
    @Log
    public class EmployeeStateMachineConfig extends StateMachineConfigurerAdapter<EmployeeStates, EmployeeEvents> {
    
    
    }
    

    【讨论】:

      【解决方案5】:

      对我来说,问题是由于不匹配泛型类型参数引起的。因此,我使用 StateMachineStateConfigurer&lt;String, String&gt; 而不是 StateMachineStateConfigurer&lt;States, Events&gt;,因此未定义 bean 的 &lt;States, Events&gt; 版本。

      在您的情况下,检查“States”的导入和“Events”的导入,以确保它们是 bean 定义中的相同类以及您在 @Autowired 中使用它的位置。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-22
        • 2015-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-29
        • 2015-05-09
        • 1970-01-01
        相关资源
        最近更新 更多