工作流系列--ProcessEngineAutoConfiguration分析

Posted by 张伟真 on 2024-11-02
Estimated Reading Time 5 Minutes
Words 1.2k In Total
Viewed Times

工作流系列 – ProcessEngineAutoConfiguration分析

上一篇章我们讲到,找到了入口配置类,那今天我们就来讲讲这个配置类究竟做了啥,有什么魔法
自动装配又装了哪些东西
类的继承关系如下图
类继承图

从ProcessEngineAutoConfiguration源码第一部分,装配了一个配置Bean,这个配置bean是整个流程的基础,规定了流程用什么序列化json,数据源,ssl,tls等等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@Bean
@ConditionalOnMissingBean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(
DataSource dataSource,
PlatformTransactionManager transactionManager,
SpringAsyncExecutor springAsyncExecutor,
ActivitiProperties activitiProperties,
ProcessDefinitionResourceFinder processDefinitionResourceFinder,
@Autowired(required = false) List<ProcessEngineConfigurationConfigurer> processEngineConfigurationConfigurers,
@Autowired(required = false) List<ProcessEngineConfigurator> processEngineConfigurators) throws IOException {

SpringProcessEngineConfiguration conf = new SpringProcessEngineConfiguration();
conf.setConfigurators(processEngineConfigurators);
configureProcessDefinitionResources(processDefinitionResourceFinder,
conf);
conf.setDataSource(dataSource);
conf.setTransactionManager(transactionManager);

conf.setAsyncExecutor(springAsyncExecutor);
conf.setDeploymentName(activitiProperties.getDeploymentName());
conf.setDatabaseSchema(activitiProperties.getDatabaseSchema());
conf.setDatabaseSchemaUpdate(activitiProperties.getDatabaseSchemaUpdate());
conf.setDbHistoryUsed(activitiProperties.isDbHistoryUsed());
conf.setAsyncExecutorActivate(activitiProperties.isAsyncExecutorActivate());
addAsyncPropertyValidator(activitiProperties,
conf);
conf.setMailServerHost(activitiProperties.getMailServerHost());
conf.setMailServerPort(activitiProperties.getMailServerPort());
conf.setMailServerUsername(activitiProperties.getMailServerUserName());
conf.setMailServerPassword(activitiProperties.getMailServerPassword());
conf.setMailServerDefaultFrom(activitiProperties.getMailServerDefaultFrom());
conf.setMailServerUseSSL(activitiProperties.isMailServerUseSsl());
conf.setMailServerUseTLS(activitiProperties.isMailServerUseTls());

if (userGroupManager != null) {
conf.setUserGroupManager(userGroupManager);
}

conf.setHistoryLevel(activitiProperties.getHistoryLevel());
conf.setCopyVariablesToLocalForTasks(activitiProperties.isCopyVariablesToLocalForTasks());
conf.setSerializePOJOsInVariablesToJson(activitiProperties.isSerializePOJOsInVariablesToJson());
conf.setJavaClassFieldForJackson(activitiProperties.getJavaClassFieldForJackson());

if (activitiProperties.getCustomMybatisMappers() != null) {
conf.setCustomMybatisMappers(getCustomMybatisMapperClasses(activitiProperties.getCustomMybatisMappers()));
}

if (activitiProperties.getCustomMybatisXMLMappers() != null) {
conf.setCustomMybatisXMLMappers(new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
}

if (activitiProperties.getCustomMybatisXMLMappers() != null) {
conf.setCustomMybatisXMLMappers(new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
}

if (activitiProperties.isUseStrongUuids()) {
conf.setIdGenerator(new StrongUuidGenerator());
}

if (activitiProperties.getDeploymentMode() != null) {
conf.setDeploymentMode(activitiProperties.getDeploymentMode());
}

if (processEngineConfigurationConfigurers != null) {
for (ProcessEngineConfigurationConfigurer processEngineConfigurationConfigurer : processEngineConfigurationConfigurers) {
processEngineConfigurationConfigurer.configure(conf);
}
}
springAsyncExecutor.applyConfig(conf);
return conf;
}

我们再看看SpringProcessEngineConfiguration里面做了啥,里面做了一些自动部署相关的一些东西,值得注意的是这里有个buildProcessEngine构建了一个流程引擎,这个很关键,可以看下引用
pringProcessEngineConfiguration源码

在processEngineConfiguration的注释中可以看出,如果需要自定义配置可以在buildProcessEngine方法调用之前,说明构建流程引擎就在buildProcessEngine这一步做的,深入看下这个类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
* Configuration information from which a process engine can be build.
*
* <p>
* Most common is to create a process engine based on the default configuration file:
*
* <pre>
* ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault().buildProcessEngine();
* </pre>
*
* </p>
*
* <p>
* To create a process engine programmatic, without a configuration file, the first option is {@link #createStandaloneProcessEngineConfiguration()}
*
* <pre>
* ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration().buildProcessEngine();
* </pre>
*
* This creates a new process engine with all the defaults to connect to a remote h2 database (jdbc:h2:tcp://localhost/activiti) in standalone mode. Standalone mode means that Activiti will manage the
* transactions on the JDBC connections that it creates. One transaction per service method. For a description of how to write the configuration files, see the userguide.
* </p>
*
* <p>
* The second option is great for testing: {@link #createStandalonInMemeProcessEngineConfiguration()}
*
* <pre>
* ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration().buildProcessEngine();
* </pre>
*
* This creates a new process engine with all the defaults to connect to an memory h2 database (jdbc:h2:tcp://localhost/activiti) in standalone mode. The DB schema strategy default is in this case
* <code>create-drop</code>. Standalone mode means that Activiti will manage the transactions on the JDBC connections that it creates. One transaction per service method.
* </p>
*
* <p>
* On all forms of creating a process engine, you can first customize the configuration before calling the {@link #buildProcessEngine()} method by calling any of the setters like this:
*
* <pre>
* ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResourceDefault().setMailServerHost(&quot;gmail.com&quot;).setJdbcUsername(&quot;mickey&quot;).setJdbcPassword(&quot;mouse&quot;)
* .buildProcessEngine();
* </pre>
*
* </p>
*
* @see ProcessEngines

*/

buildProcessEngine调用了父类的buildProcessEngine,而父类的buidPeocessEngine则是init初始化了一堆的东西,看明白这块就知道流程里面有多少东西了,这里包括了流程的配置,流程解析器,事项工厂,各种管理器,
这里值得注意的是几个Factory工厂的初始化,看完了这几个初始化方法,可以看出activiti用了命令模式,责任链模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
@Override
public ProcessEngine buildProcessEngine() {
init();
ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
postProcessEngineInitialisation();

return processEngine;
}

// init
// /////////////////////////////////////////////////////////////////////

public void init() {
initConfigurators();
configuratorsBeforeInit();
initHistoryLevel();
initExpressionManager();

if (usingRelationalDatabase) {
initDataSource();
}

initAgendaFactory();
initHelpers();
initVariableTypes();
initBeans();
initScriptingEngines();
initClock();
initBusinessCalendarManager();
initCommandContextFactory();
initTransactionContextFactory();
initCommandExecutors();
initServices();
initIdGenerator();
initBehaviorFactory();
initListenerFactory();
initBpmnParser();
initProcessDefinitionCache();
initProcessDefinitionInfoCache();
initKnowledgeBaseCache();
initJobHandlers();
initJobManager();
initAsyncExecutor();

initTransactionFactory();

if (usingRelationalDatabase) {
initSqlSessionFactory();
}

initSessionFactories();
initDataManagers();
initEntityManagers();
initHistoryManager();
initJpa();
initDeployers();
initDelegateInterceptor();
initEventHandlers();
initFailedJobCommandFactory();
initEventDispatcher();
initProcessValidator();
initDatabaseEventLogging();
configuratorsAfterInit();
}

initCommandContextFactory()方法初始化了一个命令工厂,new了一个CommandContextFactory,CommandContextFactory中持有当前processEngineConfiguration的引用
命令模式2

为什么能看出用了命令模式,还是从initCommandExecutors()说起,这里典型的命令模式的构造,Invoker,Executor
命令模式3

初始化拦截器interceptor(),这里用了责任链模式构造了一个拦截器链,而且拦截器链的最后是CommandInvoker,并且将第一个拦截器放到CommandExecutor里面
命令模式1
拦截器模式1
上图可以看出commandExecutor持有拦截器的头

接着初始化服务 initServices(),将commandExecutor设置到服务里面,这里可以看出引擎暴露出来可以用的服务有哪些,跟数据库表结构相呼应
初始化服务

初始化各个组件以后,new了一个ProcessEngineImpl,并将当前的配置ProcessEngineConfiguration赋值给它
因此,这个代表流程引擎的ProcessEngine就变成了一个基础的入口类,提供了对工作流操作的所有服务的访问。
入口类

剩下的装配的几个bean 是资源发现,部署事件生产者,还有一些配置类的Bean,没有太细太深层的东西,下以篇继续讲讲CommandContextInterceptor
在上面的源码分析中出现的,觉得挺有意思的一个一个类


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !