activiti源码剖析--流程引擎ProcessEngine的
感谢冀正,张志祥前辈《Activiti权威指南》
activiti源码剖析--流程引擎ProcessEngine的获取
前言
本篇文章通过源码进行分析ProcessEngine是如何被创建出来,在学习activiti的同时,通过源码进行分析以对activiti流程引擎进行更深层次的理解深入。
一、流程配置文件
Acticiti配置文件的风格使用了Spring中的文件配置方式,这样有什么好处呢?那当然从Spring的特性IOC说起,依赖注入,控制反转,这里就不再多说,选取这样的配置方式也说明了,Activiti在设计之时就考虑到了与spring的融合。activiti的配置文件类型分为 普通配置 和Spring配置(这里说明一下,activiti的配置文件方式采用Spring方式,但是activiti可以集成Spring开发,也可以不集成,所以后者的Spring配置方式其实也就是集成Spring进行开发)
- 普通配置文件名称为activiti.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti" />
<property name="jdbcDriver" value="com.mysql.jdbc.Driver" />
<property name="jdbcUsername" value="root" />
<property name="jdbcPassword" value="1234" />
<property name="databaseSchemaUpdate" value="true" />
</bean>
</beans>
- Spring配置文件名称为activiti-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_activiti"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置注解方式配置事务-->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
<!--定义基于Spring的引擎配置对象BEAN-->
<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="dataSource" ref="dataSource"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="databaseSchemaUpdate" value="true"/>
<property name="deploymentResources" value="classpath:userAndGroupTest.bpmn20.xml"/>
<!--<property name="jobExecutorActivate" value="false"/>-->
</bean>
<!--配置引擎工厂对象BEAN-->
<bean id="processEngineFactory" class="org.activiti.spring.ProcessEngineFactoryBean">
<property name="processEngineConfiguration" ref="processEngineConfiguration"/>
</bean>
<!--使用spring提供的工厂方式获取actititi7个service接口对象-->
<bean id="repositoryService" factory-bean="processEngineFactory" factory-method="getRepositoryService"/>
....7大服务
</beans>
二、构造流程引擎实例对象
获取流程引擎实例对象代码如下
ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine();
//这里也可以通过自定义流程引擎名称获取
//ProcessEngines.getProcessEngine(String processEngineName)
RepositoryService repositoryService = defaultProcessEngine.getRepositoryService();
assert repositoryService !=null;
ProcessEngines:该类负责管理所有的流程引擎ProcessEngine集合,并负责流程引擎实例对象的注册、获取、注销等操作。
只需要ProcessEngines.getDefaultProcessEngine();一句话即可获取到我们的重要角色:processEngine,那么它是怎么被获取到的呢?接下来围绕这一话题进行源码剖析。
ProcessEngines.java源码
public static ProcessEngine getDefaultProcessEngine() {
return getProcessEngine("default");
}
相信从这里也可看出来,在通过ProcessEngines获取流程引擎的时候,不管使用默认的方式还是通过指定流程引擎名称,其实都是调用的ProcessEngine(processEngineName)方法获取
public static ProcessEngine getProcessEngine(String processEngineName) {
if (!isInitialized()) {
init();
}
return (ProcessEngine)processEngines.get(processEngineName);
}
在获取流程引擎的前提要先进行初始化。如果已经完成初始化,那么返回指定名称的流程引擎对象。从这里也可以看出Activiti支持多个流程引擎实例对象一起运行,通过流程引擎名称进行区分。
protected static Map<String, ProcessEngine> processEngines = new HashMap();
在这里processEngines为MAP结构,key为流程引擎名称,value为流程引擎实例对象。
接下来看看Activiti是如何做初始化准备工作的
public static synchronized void init() {
if (!isInitialized()) {
if (processEngines == null) {
processEngines = new HashMap();
}
ClassLoader classLoader = ReflectUtil.getClassLoader();
Enumeration resources = null;
try {
resources = classLoader.getResources("activiti.cfg.xml");
} catch (IOException var6) {
throw new ActivitiIllegalArgumentException("problem retrieving activiti.cfg.xml resources on the classpath: " + System.getProperty("java.class.path"), var6);
}
HashSet configUrls = new HashSet();
while(resources.hasMoreElements()) {
configUrls.add(resources.nextElement());
}
Iterator iterator = configUrls.iterator();
while(iterator.hasNext()) {
URL resource = (URL)iterator.next();
log.info("Initializing process engine using configuration '{}'", resource.toString());
initProcessEngineFromResource(resource);
}
try {
resources = classLoader.getResources("activiti-context.xml");
} catch (IOException var5) {
throw new ActivitiIllegalArgumentException("problem retrieving activiti-context.xml resources on the classpath: " + System.getProperty("java.class.path"), var5);
}
while(resources.hasMoreElements()) {
URL resource = (URL)resources.nextElement();
log.info("Initializing process engine using Spring configuration '{}'", resource.toString());
initProcessEngineFromSpringResource(resource);
}
setInitialized(true);
} else {
log.info("Process engines already initialized");
}
}
首先再次判断确认流程引擎是否已经被初始化。 接下的工作就是定位activiti配置文件啦,(在这里可以看到是从根路径中加载配置文件,为什么的话,可以从这里补充补充知识getClass().getResource()和classLoader.getResource())这里也可以看出activiti配置文件的名称啦。
普通配置文件(activiti.cfg.xml)通过initProcessEngineFromResource(resource);进行初始化加载,集成spring配置文件通过initProcessEngineFromSpringResource(resource);进行初始化加载。
2.1、初始化流程引擎之普通配置文件
再进入initProcessEngineFromResource(resource)首先是做了大量的准备工作,准备工作其实也就是清除已经存在同名称的流程引擎信息,之后调用buildProcessEngine(resourceUrl)构造流程引擎实例对象,然后放入新的流程引擎信息相关信息。
private static ProcessEngine buildProcessEngine(URL resource) {
InputStream inputStream = null;
ProcessEngine var3;
try {
inputStream = resource.openStream();
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);
var3 = processEngineConfiguration.buildProcessEngine();
} catch (IOException var7) {
throw new ActivitiIllegalArgumentException("couldn't open resource stream: " + var7.getMessage(), var7);
} finally {
IoUtil.closeSilently(inputStream);
}
return var3;
}
在 buildProcessEngine(resourceUrl) 中进入ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);核心代码
public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream) {
return createProcessEngineConfigurationFromInputStream(inputStream, "processEngineConfiguration");
}
public static ProcessEngineConfiguration createProcessEngineConfigurationFromInputStream(InputStream inputStream, String beanName) {
return BeansConfigurationHelper.parseProcessEngineConfigurationFromInputStream(inputStream, beanName);
}
从以上代码可以看出是在获取通过spring容器管理的id为processEngineConfiguration的bean对象。即org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration(配置文件中配置)。之后Spring会解析xml配置文件实例化org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration对象
ProcessEngineConfigurationImpl类结构.png在实例化org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration的同时,也会对其父类进行初始化,点击ProcessEngineConfigurationImpl类进入查看
protected RepositoryService repositoryService = new RepositoryServiceImpl();
protected RuntimeService runtimeService = new RuntimeServiceImpl();
protected HistoryService historyService = new HistoryServiceImpl(this);
protected IdentityService identityService = new IdentityServiceImpl();
protected TaskService taskService = new TaskServiceImpl(this);
protected FormService formService = new FormServiceImpl();
protected ManagementService managementService = new ManagementServiceImpl();
protected DynamicBpmnService dynamicBpmnService = new DynamicBpmnServiceImpl(this);
也就是在进行各种服务类对象的初始化。在这里完成了对流程引擎配置对象的初始化,注意上述buildProcessEngine(resourceUrl)中在初始化流程引擎配置对象之后,通过流程引擎配置对象来build processEngine,var3 = processEngineConfiguration.buildProcessEngine();这里方法的实现是在各种配置类的父类(ProcessEngineConfigurationImpl)中进行了实现
ProcessEngineConfigurationImpl.java
public ProcessEngine buildProcessEngine() {
this.init();
ProcessEngineImpl processEngine = new ProcessEngineImpl(this);
if (this.isActiviti5CompatibilityEnabled && this.activiti5CompatibilityHandler != null) {
Context.setProcessEngineConfiguration(processEngine.getProcessEngineConfiguration());
this.activiti5CompatibilityHandler.getRawProcessEngine();
}
this.postProcessEngineInitialisation();
return processEngine;
}
该操作完成了以下操作:
-
调用init方法初始化了各种属性值
这里呢就是对一些诸如数据源、配置器、流程图片生成器、表达式管理器等一系列的初始化。
-
实例化ProcessEngineImpl类
那么这里就是实例化流程引擎的重头戏了。看代码实现
public ProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
this.processEngineConfiguration = processEngineConfiguration;
this.name = processEngineConfiguration.getProcessEngineName();
this.repositoryService = processEngineConfiguration.getRepositoryService();
....这里就是在填充7大服务对象
this.dynamicBpmnService = processEngineConfiguration.getDynamicBpmnService();
this.asyncExecutor = processEngineConfiguration.getAsyncExecutor();//异步作业执行器
this.commandExecutor = processEngineConfiguration.getCommandExecutor();//命令执行器
this.sessionFactories = processEngineConfiguration.getSessionFactories();
this.transactionContextFactory = processEngineConfiguration.getTransactionContextFactory();//事务
...
if (processEngineConfiguration.isUsingRelationalDatabase() && processEngineConfiguration.getDatabaseSchemaUpdate() != null) {
this.commandExecutor.execute(processEngineConfiguration.getSchemaCommandConfig(), new SchemaOperationsProcessEngineBuild());//这里就是通过databaseSchemaUpdate值进行数据库生成策略
}
...
ProcessEngines.registerProcessEngine(this);//注册流程引擎
if (this.asyncExecutor != null && this.asyncExecutor.isAutoActivate()) {
this.asyncExecutor.start();//启动异步执行器
}
if (processEngineConfiguration.getProcessEngineLifecycleListener() != null) {
processEngineConfiguration.getProcessEngineLifecycleListener().onProcessEngineBuilt(this);//触发流程引擎生命周期监听器
}
processEngineConfiguration.getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createGlobalEvent(ActivitiEventType.ENGINE_CREATED));
}
上述代码看出,在对一些属性装配完成之后,操作引擎表(具体策略以及如何生成看这里activiti源码剖析之操作引擎表)之后注册流程引擎,也就是将processEngineImpl实例对象注册进ProssEngines中,到这里想必已经明白了文章开始代码,ProcessEngines是如何获取到processEngine的。
到这里,大致已经明白是ProcessEngine流程引擎是如何初始化并且注册进processEngines流程引擎管理对象了。