13. State Machine Factories
当状态机需要动态创建而不是在编译时定义静态配置时,有一些用例。 例如,如果有自定义组件正在使用自己的状态机,并且这些组件是动态创建的,则在应用程序启动过程中不可能有静态加工的构建。 内部状态机总是通过工厂接口构建,然后用户可以选择以编程方式使用此功能。 状态机工厂的配置与本文中各种状态机配置是硬编码的例子中所见的完全相同。
13.1 Factory via Adapter
实际上,使用@EnableStateMachine创建状态机将通过工厂工作,因此@EnableStateMachineFactory仅通过其接口公开该工厂。
@Configuration
@EnableStateMachineFactory
public class Config6
extends EnumStateMachineConfigurerAdapter<States, Events> {
@Override
public void configure(StateMachineStateConfigurer<States, Events> states)
throws Exception {
states
.withStates()
.initial(States.S1)
.end(States.SF)
.states(EnumSet.allOf(States.class));
}
}
现在您已经使用@EnableStateMachineFactory创建了一个工厂而不是状态机bean,它可以被注入并按原样用于请求新的状态机。
public class Bean3 {
@Autowired
StateMachineFactory<States, Events> factory;
void method() {
StateMachine<States,Events> stateMachine = factory.getStateMachine();
stateMachine.start();
}
}
13.1.1 Adapter Factory Limitations
工厂目前的限制是,它与所创建的状态机关联的所有操作和警戒将共享相同的实例。 这意味着从你的行为和警惕你需要专门处理一个情况,即相同的bean将被不同的状态机调用。 这个限制是在将来的版本中可以解决的。
13.2 State Machine via Builder
使用上面显示的适配器有一个限制,因为它需要通过Spring @Configuration类和应用程序上下文来工作。 虽然这是配置状态机实例的非常明确的模型,但它会限制编译时的配置,而这并不总是用户想要做的。 如果需要构建更多动态状态机,则可以使用简单的构建器模式构建类似的实例。 使用字符串作为状态和事件,这个构建器模式可以用来在Spring应用程序上下文之外构建完全动态的状态机,如上所示。
StateMachine<String, String> buildMachine1() throws Exception {
Builder<String, String> builder = StateMachineBuilder.builder();
builder.configureStates()
.withStates()
.initial("S1")
.end("SF")
.states(new HashSet<String>(Arrays.asList("S1","S2","S3","S4")));
return builder.build();
}
Builder在使用适配器类的@Configuration模型的幕后使用相同的配置接口。 同样的模型可以通过构建器的方法来配置转换,状态和通用配置。 这只是意味着无论您可以使用普通的EnumStateMachineConfigurerAdapter或StateMachineConfigurerAdapter,都可以通过构建器动态使用。
目前builder.configureStates(),builder.configureTransitions()和builder.configureConfiguration()接口方法不能链接在一起,这意味着构建器方法需要单独调用。
StateMachine<String, String> buildMachine2() throws Exception {
Builder<String, String> builder = StateMachineBuilder.builder();
builder.configureConfiguration()
.withConfiguration()
.autoStartup(false)
.beanFactory(null)
.taskExecutor(null)
.taskScheduler(null)
.listener(null);
return builder.build();
}
了解常见配置需要与从构建器实例化的机器一起使用的情况很重要。 从withConfiguration()返回的配置器可用于设置autoStart,TaskScheduler,TaskExecutor,BeanFactory并另外注册一个StateMachineListener。 如果从构建器返回的StateMachine实例通过@Bean注册为一个bean,即自动附加BeanFactory,然后可以从那里找到默认的TaskExecutor。 如果实例在Spring应用程序上下文之外使用,则必须使用这些方法来设置所需的工具。