简析flowable流程引擎的创建

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注入。

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值