Overview
flowable流程引擎支持以下三种方式来进行引擎创建:
- 普通文件加载方式 : 通过代码加载flowable.cfg.xml和flowable.context.xml来创建引擎。
- Spring方式: 通过容器生命周期LifeCycle回调,加载上述文件来创建引擎。
- Springboot方式: 通过auto-configure机制自动加载配置,创建引擎。
本文主要来解释一下springboot这种方式。
流程引擎创建
flowable与springboot集成的方式中,配置的核心文件就是ProcessEngineAutoConfiguration,代码如下:
@Configuration
@ConditionalOnProcessEngine
@EnableConfigurationProperties({
FlowableProperties.class,
FlowableMailProperties.class,
FlowableProcessProperties.class,
FlowableIdmProperties.class
})
@AutoConfigureAfter({
FlowableTransactionAutoConfiguration.class
})
@Import({
FlowableJobConfiguration.class
})
public class ProcessEngineAutoConfiguration extends AbstractSpringEngineAutoConfiguration {
@Autowired(required = false)
private List<EngineConfigurationConfigurer<SpringProcessEngineConfiguration>> processEngineConfigurationConfigurers = new ArrayList<>();
protected final FlowableProcessProperties processProperties;
protected final FlowableIdmProperties idmProperties;
protected final FlowableMailProperties mailProperties;
public ProcessEngineAutoConfiguration(FlowableProperties flowableProperties, FlowableProcessProperties processProperties,
FlowableIdmProperties idmProperties, FlowableMailProperties mailProperties) {
super(flowableProperties);
this.processProperties = processProperties;
this.idmProperties = idmProperties;
this.mailProperties = mailProperties;
}
/**
* The Async Executor must not be shared between the engines.
* Therefore a dedicated one is always created.
*/
@Bean
@Process
@ConfigurationProperties(prefix = "flowable.process.async.executor")
@ConditionalOnMissingBean(name = "processAsyncExecutor")
public SpringAsyncExecutor processAsyncExecutor(
ObjectProvider<TaskExecutor> taskExecutor,
@Process ObjectProvider<TaskExecutor> processTaskExecutor,
ObjectProvider<SpringRejectedJobsHandler> rejectedJobsHandler,
@Process ObjectProvider<SpringRejectedJobsHandler> processRejectedJobsHandler
) {
return new SpringAsyncExecutor(
getIfAvailable(processTaskExecutor, taskExecutor),
getIfAvailable(processRejectedJobsHandler, rejectedJobsHandler)
);
}
@Bean
@ConditionalOnMissingBean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(DataSource dataSource, PlatformTransactionManager platformTransactionManager,
@Process ObjectProvider<AsyncExecutor> asyncExecutorProvider) throws IOException {
SpringProcessEngineConfiguration conf = new SpringProcessEngineConfiguration();
List<Resource> resources = this.discoverDeploymentResources(
flowableProperties.getProcessDefinitionLocationPrefix(),
flowableProperties.getProcessDefinitionLocationSuffixes(),
flowableProperties.isCheckProcessDefinitions()
);
if (resources != null && !resources.isEmpty()) {
conf.setDeploymentResources(resources.toArray(new Resource[0]));
conf.setDeploymentName(flowableProperties.getDeploymentName());
}
AsyncExecutor springAsyncExecutor = asyncExecutorProvider.getIfUnique();
if (springAsyncExecutor != null) {
conf.setAsyncExecutor(springAsyncExecutor);
}
configureSpringEngine(conf, platformTransactionManager);
configureEngine(conf, dataSource);
conf.setDeploymentName(defaultText(flowableProperties.getDeploymentName(), conf.getDeploymentName()));
conf.setDisableIdmEngine(!(flowableProperties.isDbIdentityUsed() && idmProperties.isEnabled()));
conf.setAsyncExecutorActivate(flowableProperties.isAsyncExecutorActivate());
conf.setMailServerHost(mailProperties.getHost());
conf.setMailServerPort(mailProperties.getPort());
conf.setMailServerUsername(mailProperties.getUsername());
conf.setMailServerPassword(mailProperties.getPassword());
conf.setMailServerDefaultFrom(mailProperties.getDefaultFrom());
conf.setMailServerUseSSL(mailProperties.isUseSsl());
conf.setMailServerUseTLS(mailProperties.isUseTls());
conf.setEnableProcessDefinitionHistoryLevel(processProperties.isEnableProcessDefinitionHistoryLevel());
conf.setProcessDefinitionCacheLimit(processProperties.getDefinitionCacheLimit());
conf.setEnableSafeBpmnXml(processProperties.isEnableSafeXml());
conf.setHistoryLevel(flowableProperties.getHistoryLevel());
processEngineConfigurationConfigurers.forEach(configurator -> configurator.configure(conf));
return conf;
}
@Bean
public ProcessEngineFactoryBean processEngine(SpringProcessEngineConfiguration configuration) throws Exception {
ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean();
processEngineFactoryBean.setProcessEngineConfiguration(configuration);
return processEngineFactoryBean;
}
@Bean
@ConditionalOnMissingBean
public RuntimeService runtimeServiceBean(ProcessEngine processEngine) {
return processEngine.getRuntimeService();
}
@Bean
@ConditionalOnMissingBean
public RepositoryService repositoryServiceBean(ProcessEngine processEngine) {
return processEngine.getRepositoryService();
}
@Bean
@ConditionalOnMissingBean
public TaskService taskServiceBean(ProcessEngine processEngine) {
return processEngine.getTaskService();
}
@Bean
@ConditionalOnMissingBean
public HistoryService historyServiceBean(ProcessEngine processEngine) {
return processEngine.getHistoryService();
}
@Bean
@ConditionalOnMissingBean
public ManagementService managementServiceBean(ProcessEngine processEngine) {
return processEngine.getManagementService();
}
@Bean
@ConditionalOnMissingBean
public DynamicBpmnService dynamicBpmnServiceBean(ProcessEngine processEngine) {
return processEngine.getDynamicBpmnService();
}
@Bean
@ConditionalOnMissingBean
public FormService formServiceBean(ProcessEngine processEngine) {
return processEngine.getFormService();
}
@Bean
@ConditionalOnMissingBean
public IdentityService identityServiceBean(ProcessEngine processEngine) {
return processEngine.getIdentityService();
}
}
代码有点长,不过一讲您就明白了,主要包括如下几件事情:
- 加载flowable配置(在applicaiton.properties中)到POJO对象里,然后通过构造器注入的方式注入ProcessEngineAutoConfiguration对象。
@Configuraiton @EnableConfigurationProperties({ FlowableProperties.class, FlowableMailProperties.class, FlowableProcessProperties.class, FlowableIdmProperties.class }) public class ProcessEngineAutoConfiguration extends AbstractSpringEngineAutoConfiguration { @Autowired(required = false) private List<EngineConfigurationConfigurer<SpringProcessEngineConfiguration>> processEngineConfigurationConfigurers = new ArrayList<>(); protected final FlowableProcessProperties processProperties; protected final FlowableIdmProperties idmProperties; protected final FlowableMailProperties mailProperties; public ProcessEngineAutoConfiguration(FlowableProperties flowableProperties, FlowableProcessProperties processProperties, FlowableIdmProperties idmProperties, FlowableMailProperties mailProperties) { super(flowableProperties); this.processProperties = processProperties; this.idmProperties = idmProperties; this.mailProperties = mailProperties; }
- 实例化ProcessEngineFactoryBean对象processEngine,然后通过@Bean的参数方式实例化ProcessEngine对象并注入Spring容器。这个地方有点绕,可以参考下方链接深入了解。
@Bean public ProcessEngineFactoryBean processEngine(SpringProcessEngineConfiguration configuration) throws Exception { ProcessEngineFactoryBean processEngineFactoryBean = new ProcessEngineFactoryBean(); processEngineFactoryBean.setProcessEngineConfiguration(configuration); return processEngineFactoryBean; } @Bean @ConditionalOnMissingBean public RuntimeService runtimeServiceBean(ProcessEngine processEngine) { return processEngine.getRuntimeService(); }
- 通过已经实例化的ProcessEngine对象,实例化对象RuntimeService, TaskService等。
@Bean @ConditionalOnMissingBean public RuntimeService runtimeServiceBean(ProcessEngine processEngine) { return processEngine.getRuntimeService(); } @Bean @ConditionalOnMissingBean public RepositoryService repositoryServiceBean(ProcessEngine processEngine) { return processEngine.getRepositoryService(); } @Bean @ConditionalOnMissingBean public TaskService taskServiceBean(ProcessEngine processEngine) { return processEngine.getTaskService(); } ...
至此flowable容器的流程引擎,以及服务对象都已创建完毕,您已经可以为所欲为了。
流程引擎初始化
流程引擎的主要初始化逻辑在ProcessEngineConfigurationImpl内中,代码如下:
public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfiguration implements ScriptingEngineAwareEngineConfiguration {
...
public static final String DEFAULT_MYBATIS_MAPPING_FILE = "org/flowable/db/mapping/mappings.xml";
...
public void init() {
initConfigurators();
configuratorsBeforeInit();
initProcessDiagramGenerator();
initHistoryLevel();
initFunctionDelegates();
initDelegateInterceptor();
initExpressionManager();
initAgendaFactory();
if (usingRelationalDatabase) {
initDataSource();
initDbSchemaManagers();
}
initHelpers();
initVariableTypes();
initBeans();
initFormEngines();
initFormTypes();
initScriptingEngines();
initClock();
initBusinessCalendarManager();
initCommandContextFactory();
initTransactionContextFactory();
initCommandExecutors();
initServices();
initIdGenerator();
initWsdlImporterFactory();
initBehaviorFactory();
initListenerFactory();
initBpmnParser();
initProcessDefinitionCache();
initProcessDefinitionInfoCache();
initAppResourceCache();
initKnowledgeBaseCache();
initJobHandlers();
initHistoryJobHandlers();
initTransactionFactory();
if (usingRelationalDatabase) {
initSqlSessionFactory();
}
initSessionFactories();
initDataManagers();
initEntityManagers();
initCandidateManager();
initHistoryManager();
initDynamicStateManager();
initJpa();
initDeployers();
initEventHandlers();
initFailedJobCommandFactory();
initEventDispatcher();
initProcessValidator();
initFormFieldHandler();
initDatabaseEventLogging();
initFlowable5CompatibilityHandler();
initVariableServiceConfiguration();
initIdentityLinkServiceConfiguration();
initTaskServiceConfiguration();
initJobServiceConfiguration();
initAsyncExecutor();
initAsyncHistoryExecutor();
configuratorsAfterInit();
afterInitTaskServiceConfiguration();
}
...
}
可以看出:
- 引擎初始化大部分内容都是在此类中。
- Mapping文件所在位置:flowable-engine.jar!org/flowable/db/mapping/mappings.xml
工作流部署
SpringProcessEngineConfiguration实现了SmartLifeCycle接口,这个接口是Spring容器的生命周期接口,会在Spring容器初始化成功后部署bpmn流程。
public class SpringProcessEngineConfiguration extends ProcessEngineConfigurationImpl implements SpringEngineConfiguration {
...
@Override
public void start() {
synchronized (lifeCycleMonitor) {
if (!isRunning()) {
enginesBuild.forEach(name -> autoDeployResources(ProcessEngines.getProcessEngine(name)));
running = true;
}
}
}
...
}
public interface SpringEngineConfiguration extends ApplicationContextAware, SmartLifecycle {
...
}
我们从上述代码中可以看出:
- SpringProcessEngineConfiguration继承了SmartLifeCycle接口
- start()实现了流程的部署。
总结
与springboot的集成中,需要关注一下几点:
- flowable通过springboot的autoconfigure机制来启动工作流引擎。
- flowable通过Spring life cycle接口来自动部署工作流。
- 各种服务对象对会被容器实例化,使用时可直接@Autowired注入。