感謝冀正,張志祥前輩《Activiti權(quán)威指南》
activiti源碼剖析--流程引擎ProcessEngine的獲取
前言
本篇文章通過源碼進行分析ProcessEngine是如何被創(chuàng)建出來热凹,在學習activiti的同時宽闲,通過源碼進行分析以對activiti流程引擎進行更深層次的理解深入。
一弊知、流程配置文件
Acticiti配置文件的風格使用了Spring中的文件配置方式阻逮,這樣有什么好處呢?那當然從Spring的特性IOC說起秩彤,依賴注入叔扼,控制反轉(zhuǎn),這里就不再多說漫雷,選取這樣的配置方式也說明了瓜富,Activiti在設(shè)計之時就考慮到了與spring的融合。activiti的配置文件類型分為 普通配置 和Spring配置(這里說明一下降盹,activiti的配置文件方式采用Spring方式食呻,但是activiti可以集成Spring開發(fā),也可以不集成,所以后者的Spring配置方式其實也就是集成Spring進行開發(fā))
- 普通配置文件名稱為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">
<!--配置數(shù)據(jù)源-->
<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>
<!--配置事務(wù)管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入數(shù)據(jù)源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--配置注解方式配置事務(wù)-->
<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大服務(wù)
</beans>
二仅胞、構(gòu)造流程引擎實例對象
獲取流程引擎實例對象代碼如下
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獲取流程引擎的時候编整,不管使用默認的方式還是通過指定流程引擎名稱舔稀,其實都是調(diào)用的ProcessEngine(processEngineName)方法獲取
public static ProcessEngine getProcessEngine(String processEngineName) {
if (!isInitialized()) {
init();
}
return (ProcessEngine)processEngines.get(processEngineName);
}
在獲取流程引擎的前提要先進行初始化。如果已經(jīng)完成初始化掌测,那么返回指定名稱的流程引擎對象内贮。從這里也可以看出Activiti支持多個流程引擎實例對象一起運行,通過流程引擎名稱進行區(qū)分汞斧。
protected static Map<String, ProcessEngine> processEngines = new HashMap();
在這里processEngines為MAP結(jié)構(gòu)夜郁,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");
}
}
首先再次判斷確認流程引擎是否已經(jīng)被初始化竞端。 接下的工作就是定位activiti配置文件啦,(在這里可以看到是從根路徑中加載配置文件庙睡,為什么的話事富,可以從這里補充補充知識getClass().getResource()和classLoader.getResource())這里也可以看出activiti配置文件的名稱啦。
普通配置文件(activiti.cfg.xml)通過initProcessEngineFromResource(resource);進行初始化加載乘陪,集成spring配置文件通過initProcessEngineFromSpringResource(resource);進行初始化加載赵颅。
2.1、初始化流程引擎之普通配置文件
再進入initProcessEngineFromResource(resource)首先是做了大量的準備工作暂刘,準備工作其實也就是清除已經(jīng)存在同名稱的流程引擎信息饺谬,之后調(diào)用buildProcessEngine(resourceUrl)構(gòu)造流程引擎實例對象,然后放入新的流程引擎信息相關(guān)信息谣拣。
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對象
在實例化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);
也就是在進行各種服務(wù)類對象的初始化。在這里完成了對流程引擎配置對象的初始化贵涵,注意上述buildProcessEngine(resourceUrl)中在初始化流程引擎配置對象之后列肢,通過流程引擎配置對象來build processEngine,var3 = processEngineConfiguration.buildProcessEngine();這里方法的實現(xiàn)是在各種配置類的父類(ProcessEngineConfigurationImpl)中進行了實現(xiàn)
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;
}
該操作完成了以下操作:
-
調(diào)用init方法初始化了各種屬性值
這里呢就是對一些諸如數(shù)據(jù)源恰画、配置器、流程圖片生成器瓷马、表達式管理器等一系列的初始化拴还。
-
實例化ProcessEngineImpl類
那么這里就是實例化流程引擎的重頭戲了∨菲福看代碼實現(xiàn)
public ProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
this.processEngineConfiguration = processEngineConfiguration;
this.name = processEngineConfiguration.getProcessEngineName();
this.repositoryService = processEngineConfiguration.getRepositoryService();
....這里就是在填充7大服務(wù)對象
this.dynamicBpmnService = processEngineConfiguration.getDynamicBpmnService();
this.asyncExecutor = processEngineConfiguration.getAsyncExecutor();//異步作業(yè)執(zhí)行器
this.commandExecutor = processEngineConfiguration.getCommandExecutor();//命令執(zhí)行器
this.sessionFactories = processEngineConfiguration.getSessionFactories();
this.transactionContextFactory = processEngineConfiguration.getTransactionContextFactory();//事務(wù)
...
if (processEngineConfiguration.isUsingRelationalDatabase() && processEngineConfiguration.getDatabaseSchemaUpdate() != null) {
this.commandExecutor.execute(processEngineConfiguration.getSchemaCommandConfig(), new SchemaOperationsProcessEngineBuild());//這里就是通過databaseSchemaUpdate值進行數(shù)據(jù)庫生成策略
}
...
ProcessEngines.registerProcessEngine(this);//注冊流程引擎
if (this.asyncExecutor != null && this.asyncExecutor.isAutoActivate()) {
this.asyncExecutor.start();//啟動異步執(zhí)行器
}
if (processEngineConfiguration.getProcessEngineLifecycleListener() != null) {
processEngineConfiguration.getProcessEngineLifecycleListener().onProcessEngineBuilt(this);//觸發(fā)流程引擎生命周期監(jiān)聽器
}
processEngineConfiguration.getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createGlobalEvent(ActivitiEventType.ENGINE_CREATED));
}
上述代碼看出片林,在對一些屬性裝配完成之后,操作引擎表(具體策略以及如何生成看這里activiti源碼剖析之操作引擎表)之后注冊流程引擎怀骤,也就是將processEngineImpl實例對象注冊進ProssEngines中费封,到這里想必已經(jīng)明白了文章開始代碼,ProcessEngines是如何獲取到processEngine的蒋伦。
到這里弓摘,大致已經(jīng)明白是ProcessEngine流程引擎是如何初始化并且注冊進processEngines流程引擎管理對象了。