Для нашего случая использования я хотел бы реализовать машину состояний, в состояниях которой также должны быть машины состояний (подчиненные машины состояний), чтобы вспомогательные машины могли работать асинхронно. Я видел, что интерфейс StateConfigurer
предоставляет методы, которые принимают StateMachine
, а также StateMachineFactory
:
StateConfigurer#state(S state, StateMachine<S, E> stateMachine)
StateConfigurer#state(S state, StateMachineFactory<S, E> stateMachineFactory)
Не могли бы вы рассказать, как настроить родительский автомат состояний StateMachineConfig
с помощью второго метода, описанного выше, чтобы регионы использовали вспомогательные автоматы состояний.
Вот соответствующая часть моего кода (на основе пример Tasks ):
(для простоты я удалил события здесь)
@Configuration
public class Application implements CommandLineRunner {
private final static Log log = LogFactory.getLog(Application.class);
@Autowired
StateMachine<States, Events> stateMachine;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) {
stateMachine.start();
}
@Configuration
@EnableStateMachine
static class StateMachineConfig
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Autowired
@Qualifier("subStateMachineFactory")
private StateMachineFactory<States, Events> stateMachineFactory;
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.READY)
.fork(States.FORK)
.state(States.TASKS)
.join(States.JOIN)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T1)
.state(States.T1_PROCESSING, stateMachineFactory)
.end(States.T1E)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T2)
.state(States.T2_PROCESSING, stateMachineFactory)
.end(States.T2E)
.and()
.withStates()
.parent(States.TASKS)
.initial(States.T3)
.state(States.T3_PROCESSING, stateMachineFactory)
.end(States.T3E);
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
throws Exception {
transitions
.withExternal()
.source(States.READY).target(States.FORK)
.event(Events.RUN)
.and()
.withFork()
.source(States.FORK).target(States.TASKS)
.and()
.withExternal()
.source(States.T1).target(States.T1_PROCESSING)
.and()
.withExternal()
.source(States.T2).target(States.T2_PROCESSING)
.and()
.withExternal()
.source(States.T3).target(States.T3_PROCESSING)
.and()
.withExternal()
.source(States.T1_PROCESSING).target(States.T1E)
.and()
.withExternal()
.source(States.T2_PROCESSING).target(States.T2E)
.and()
.withExternal()
.source(States.T3_PROCESSING).target(States.T3E)
.and()
.withJoin()
.source(States.TASKS).target(States.JOIN);
}
@Bean(name = StateMachineSystemConstants.TASK_EXECUTOR_BEAN_NAME)
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
return taskExecutor;
}
}
@Configuration
@EnableStateMachineFactory(name = "subStateMachineFactory")
static class SubStateMachineConfig
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineConfigurationConfigurer<States, Events> stateMachineConfigurationConfigurer) throws Exception {
stateMachineConfigurationConfigurer
.withConfiguration()
.autoStartup(true)
.taskExecutor(subStateMachineTaskExecutor());
}
@Override
public void configure(StateMachineStateConfigurer<States, Events> stateMachineStateConfigurer)
throws Exception {
stateMachineStateConfigurer
.withStates()
.initial(States.T1_SUB)
.state(States.T1_SUB_PROCESSING)
.end(States.T1E_SUB);
}
@Override
public void configure(StateMachineTransitionConfigurer<States, Events> stateMachineTransitionConfigurer)
throws Exception {
stateMachineTransitionConfigurer
.withExternal()
.source(States.T1_SUB).target(States.T1_SUB_PROCESSING)
.action((context -> log.info(context.getStateMachine().getId() + ": T1_SUB ------> T1_SUB_PROCESSING")))
.and()
.withExternal()
.source(States.T1_SUB_PROCESSING).target(States.T1E_SUB);
}
@Bean
public TaskExecutor subStateMachineTaskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
return taskExecutor;
}
}
public enum States {
READY,
FORK, JOIN,
TASKS, T1, T1_PROCESSING, T1E, T2, T2_PROCESSING, T2E, T3, T3_PROCESSING, T3E,
T1_SUB, T1_SUB_PROCESSING, T1E_SUB
}
public enum Events {
T1_PROCESS, T2_PROCESS, T3_PROCESS, RUN,
T1_SUB_PROCESS
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@OnTransition
public @interface StatesOnTransition {
States[] source() default {};
States[] target() default {};
}
}
Версия Spring-Boot: 2.2.6.RELEASE Версия Spring-Statemachine: 2.2.0.RELEASE