flowable的部署有好几种.现在举例常用的方式:
Deployment deployment = repositoryService.createDeployment().name(bpmName).addInputStream(fileName, fileInputStream).deploy();
这里分两步先创建Deployment.然后再deploy.createDeployment()源码如下:
@Override
public DeploymentBuilder createDeployment() {
return commandExecutor.execute(new Command<DeploymentBuilder>() {
@Override
public DeploymentBuilder execute(CommandContext commandContext) {
return new DeploymentBuilderImpl(RepositoryServiceImpl.this);
}
});
}
这里是使用了建造者模式创建了一个DeploymentBuilder对象.
然后第二步是deploy.第一步中创建了一个DeploymentBuilder对象和RepositoryServiceImpl对象.部署就是通过给RepositoryServiceImpl对象注入DeploymentBuilder对象来实现的.代码如下.
@Override
public Deployment deploy() {
return repositoryService.deploy(this);
}
实现方法如下
public Deployment deploy(DeploymentBuilderImpl deploymentBuilder) {
return commandExecutor.execute(new DeployCmd<Deployment>(deploymentBuilder));
}
可以看到又是命令模式,我们看一下DeployCmd命令:部署分四步
1.插入表act_re_deployment.
2.设置部署参数,有两个isBpmn20XsdValidationEnabled和isProcessValidationEnabled都是true,都是校验.
3.实际部署.EngineDeployer,其中实际处理部署逻辑的是BpmnDeployer.这里会进入到第一个if内,找到旧的,设置为1或者旧版本+1.并且插入流程定义表act_re_procdef 中.关键源码如下.
if (deployment.isNew()) {
if (!deploymentSettings.containsKey(DeploymentSettings.IS_DERIVED_DEPLOYMENT)) {
Map<ProcessDefinitionEntity, ProcessDefinitionEntity> mapOfNewProcessDefinitionToPreviousVersion = getPreviousVersionsOfProcessDefinitions(parsedDeployment);
setProcessDefinitionVersionsAndIds(parsedDeployment, mapOfNewProcessDefinitionToPreviousVersion);
persistProcessDefinitionsAndAuthorizations(parsedDeployment);
updateTimersAndEvents(parsedDeployment, mapOfNewProcessDefinitionToPreviousVersion);
} else {
Map<ProcessDefinitionEntity, ProcessDefinitionEntity> mapOfNewProcessDefinitionToPreviousDerivedVersion =
getPreviousDerivedFromVersionsOfProcessDefinitions(parsedDeployment);
setDerivedProcessDefinitionVersionsAndIds(parsedDeployment, mapOfNewProcessDefinitionToPreviousDerivedVersion, deploymentSettings);
persistProcessDefinitionsAndAuthorizations(parsedDeployment);
}
} else {
makeProcessDefinitionsConsistentWithPersistedVersions(parsedDeployment);
}
4.发布创建实体事件.至此部署完毕.整个部署的关键代码如下:
org.flowable.engine.impl.cmd.DeployCmd#executeDeploy
// Save the data
CommandContextUtil.getDeploymentEntityManager(commandContext).insert(deployment);
if (processEngineConfiguration.getEventDispatcher().isEnabled()) {
processEngineConfiguration.getEventDispatcher().dispatchEvent(FlowableEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_CREATED, deployment));
}
// Deployment settings
Map<String, Object> deploymentSettings = new HashMap<>();
deploymentSettings.put(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED, deploymentBuilder.isBpmn20XsdValidationEnabled());
deploymentSettings.put(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED, deploymentBuilder.isProcessValidationEnabled());
// Actually deploy
processEngineConfiguration.getDeploymentManager().deploy(deployment, deploymentSettings);
if (deploymentBuilder.getProcessDefinitionsActivationDate() != null) {
scheduleProcessDefinitionActivation(commandContext, deployment);
}
if (processEngineConfiguration.getEventDispatcher().isEnabled()) {
processEngineConfiguration.getEventDispatcher().dispatchEvent(FlowableEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_INITIALIZED, deployment));
}
flowable启动流程有两种方式.最终都是执行了StartProcessInstanceCmd命令,我以流程key方式启动来分析源码,从启动流程开始.
启动流程方式:ByKey
processInstance = runtimeService.startProcessInstanceByKey(procDefKey, businessTable + ":" + businessId, vars);
这个方法内部如下
commandExecutor.execute(new StartProcessInstanceCmd<ProcessInstance>(processDefinitionKey, null, businessKey, variables));
我们看到这里使用了设计模式-命令模式,执行了一个StartProcessInstanceCmd命令.org.flowable.engine.impl.interceptor.CommandInvoker#execute方法就是获取Context.把command的结果赋值给context.
final CommandContext commandContext = Context.getCommandContext();
// Execute the command.
// This will produce operations that will be put on the agenda.
agenda.planOperation(new Runnable() {
@Override
public void run() {
commandContext.setResult(command.execute(commandContext));
}
});
我们再看一下StartProcessInstanceCmd内部.org.flowable.engine.impl.cmd.StartProcessInstanceCmd#execute方法做了两件事
1.根据CommandContext获取流程引擎配置实现类ProcessEngineConfigurationImpl
2.获取流程定义
3.启动流程实例
源码如下:
@Override
public ProcessInstance execute(CommandContext commandContext) {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
processInstanceHelper = processEngineConfiguration.getProcessInstanceHelper();
ProcessDefinition processDefinition = getProcessDefinition(processEngineConfiguration);
ProcessInstance processInstance = null;
if (hasStartFormData()) {
processInstance = handleProcessInstanceWithForm(commandContext, processDefinition, processEngineConfiguration);
} else {
processInstance = startProcessInstance(processDefinition);
}
return processInstance;
}
a.获取流程引擎配置比较简单,因为启动的时候引擎已经初始化过了.先获取引擎配置
if (commandContext != null) {
return (ProcessEngineConfigurationImpl) commandContext.getEngineConfigurations().get(EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);
}
EngineConfigurations有很多种,流程key启动时只有三种.
String KEY_PROCESS_ENGINE_CONFIG = "cfg.processEngine";
String KEY_IDM_ENGINE_CONFIG = "cfg.idmEngine";
String KEY_FORM_ENGINE_CONFIG = "cfg.formEngine";
b.我们再看获取流程定义,其实就是去数据库找流程部署表的记录.流程定义的时候会添加流程定义记录到act_re_procdef表.那么是流程引擎是怎么找到表的呢?
这就需要一个流程引擎配置类ProcessEngineConfiguration,在它的实现类中,initEntityManagers()方法和initDataManagers()分别初始化了EntihtyManager和DataManager.ProcessEngineConfigurationImpl把初始化好的DataManager注入XXXXXEntityManagerImpl里.DataManager的相当于mybatis的mapper类,定义了方法的接口.
看一下initEntityManagers()部分源码,给XXXXXEntityManagerImpl注入初始化的DataManager
if (processDefinitionEntityManager == null) {
processDefinitionEntityManager = new ProcessDefinitionEntityManagerImpl(this, processDefinitionDataManager);
}
有了流程引擎的配置信息就能获取到操作流程的数据库配置
ProcessDefinitionEntityManager processDefinitionEntityManager = processEngineConfiguration.getProcessDefinitionEntityManager();
所有操作数据库的接口都继承了EntityManager<EntityImpl extends Entity>接口,而操作实际是使用了DataManager,ProcessEngineConfigurationImpl是流程引擎的初始化类,
processDefinitionDataManager.findLatestProcessDefinitionByKey(processDefinitionKey);
processDefinitionDataManager最总使用的是sqlsession查询数据库.
(ProcessDefinitionEntity) getDbSqlSession().selectOne("selectLatestProcessDefinitionByKey", processDefinitionKey);
c.接下来是启动流程实例.上一步我们已经查询到了流程定义.现在就是流程实例的创建.是通过ProcessInstanceHelper的
createAndStartProcessInstanceWithInitialFlowElement()方法创建的.
有关键几个步骤:
1.创建流程实例(初始化,然后设置值),创建参与者信息act_ru_identitylink.发布创建实体事件.
2.插入act_hi_procinst表
3.发布创建实体事件和创建实体变量事件
4.创建第一个执行节点,插入到act_ru_execution表中.
5.更新运行时实例表ACT_RU_ACTINST
// Create the process instance
String initiatorVariableName = null;
if (initialFlowElement instanceof StartEvent) {
initiatorVariableName = ((StartEvent) initialFlowElement).getInitiator();
}
String tenantId = null;
if (overrideDefinitionTenantId != null) {
tenantId = overrideDefinitionTenantId;
} else {
tenantId = processDefinition.getTenantId();
}
ExecutionEntity processInstance = CommandContextUtil.getExecutionEntityManager(commandContext)
.createProcessInstanceExecution(processDefinition, predefinedProcessInstanceId, businessKey, tenantId,
initiatorVariableName, initialFlowElement.getId());
processInstance.setName(processInstanceName);
// Callbacks
if (callbackId != null) {
processInstance.setCallbackId(callbackId);
}
if (callbackType != null) {
processInstance.setCallbackType(callbackType);
}
CommandContextUtil.getHistoryManager(commandContext).recordProcessInstanceStart(processInstance);
boolean eventDispatcherEnabled = CommandContextUtil.getProcessEngineConfiguration().getEventDispatcher().isEnabled();
if (eventDispatcherEnabled) {
CommandContextUtil.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
FlowableEventBuilder.createEntityEvent(FlowableEngineEventType.PROCESS_CREATED, processInstance));
}
processInstance.setVariables(processDataObjects(process.getDataObjects()));
// Set the variables passed into the start command
if (variables != null) {
for (String varName : variables.keySet()) {
processInstance.setVariable(varName, variables.get(varName));
}
}
if (transientVariables != null) {
for (String varName : transientVariables.keySet()) {
processInstance.setTransientVariable(varName, transientVariables.get(varName));
}
}
// Fire events
if (eventDispatcherEnabled) {
CommandContextUtil.getProcessEngineConfiguration().getEventDispatcher()
.dispatchEvent(FlowableEventBuilder.createEntityWithVariablesEvent(FlowableEngineEventType.ENTITY_INITIALIZED, processInstance, variables, false));
}
// Create the first execution that will visit all the process definition elements
ExecutionEntity execution = CommandContextUtil.getExecutionEntityManager(commandContext).createChildExecution(processInstance);
execution.setCurrentFlowElement(initialFlowElement);
CommandContextUtil.getActivityInstanceEntityManager(commandContext).recordActivityStart(execution);
由于时间有限.最后这一步有点粗糙.下次会专门写一个文章分析启动时源码.如有疑问欢迎留言