Spring 状态机 bean 检测不工作

Spring state machine bean detection not working

我目前正在使用 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'

您可以尝试使用

@EnableStateMachine(name = "myStateMachine")

@Autowired
StateMachine<States, Events> myStateMachine;

我不知道问题出在哪里。但以下代码片段对我有用。

@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());
            }
        };
    }
}

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

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

我也遇到了同样的问题

我做到了。

有效

@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();
    }
}

在配置class中,可以添加注解@EnableStateMachineFactory就可以了,

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


}