流程的部署主要通过DeployCmd类进行:
查看部分核心代码:
public Deployment execute(CommandContext commandContext) {
// Backwards compatibility with Activiti v5
//activiti5兼容开启
if (commandContext.getProcessEngineConfiguration().isActiviti5CompatibilityEnabled()
&& deploymentBuilder.getDeploymentProperties() != null
&& deploymentBuilder.getDeploymentProperties().containsKey(DeploymentProperties.DEPLOY_AS_ACTIVITI5_PROCESS_DEFINITION)
&& deploymentBuilder.getDeploymentProperties().get(DeploymentProperties.DEPLOY_AS_ACTIVITI5_PROCESS_DEFINITION).equals(Boolean.TRUE)) {
return deployAsActiviti5ProcessDefinition(commandContext);
}
//执行部署
return executeDeploy(commandContext);
}
protected Deployment executeDeploy(CommandContext commandContext) {
//获取刚构建的部署对象
DeploymentEntity deployment = deploymentBuilder.getDeployment();
//设置部署当前时间
deployment.setDeploymentTime(commandContext.getProcessEngineConfiguration().getClock().getCurrentTime());
//在部署时会检测已部署的相同文件的最后一条记录,如果内容相同,则不会部署
if (deploymentBuilder.isDuplicateFilterEnabled()) {
//保存查到的集合
List<Deployment> existingDeployments = new ArrayList<Deployment>();
if (deployment.getTenantId() == null || ProcessEngineConfiguration.NO_TENANT_ID.equals(deployment.getTenantId())) {//TenantId不存在,通过部署名称查询数据库
//查ACT_RE_DEPLOYMENT该表
DeploymentEntity existingDeployment = commandContext.getDeploymentEntityManager().findLatestDeploymentByName(deployment.getName());
if (existingDeployment != null) {
existingDeployments.add(existingDeployment);
}
} else {//TenantId存在
List<Deployment> deploymentList = commandContext.getProcessEngineConfiguration().getRepositoryService().createDeploymentQuery().deploymentName(deployment.getName())
.deploymentTenantId(deployment.getTenantId()).orderByDeploymentId().desc().list();
if (!deploymentList.isEmpty()) {
existingDeployments.addAll(deploymentList);
}
}
DeploymentEntity existingDeployment = null;
if (!existingDeployments.isEmpty()) {
existingDeployment = (DeploymentEntity) existingDeployments.get(0);
}
//查到且和要部署的一致,则直接返回查出来的
if ((existingDeployment != null) && !deploymentsDiffer(deployment, existingDeployment)) {
return existingDeployment;
}
}
deployment.setNew(true);//设置为一个新的定义
// Save the data
//插入ACT_RE_DEPLOYMENT表(1条)和ACT_GE_BYTEARRAY表(png和bpmn定义)
commandContext.getDeploymentEntityManager().insert(deployment);
if (commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {//默认开启
//触发deployment entity被创建的事件(默认不执行任何操作,只是日志的输出等)
commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED, deployment));
}
// Deployment settings
Map<String, Object> deploymentSettings = new HashMap<String, Object>();
//bpmn2.0检查,默认开启
deploymentSettings.put(DeploymentSettings.IS_BPMN20_XSD_VALIDATION_ENABLED, deploymentBuilder.isBpmn20XsdValidationEnabled());
//process流程定义检查,默认开启
deploymentSettings.put(DeploymentSettings.IS_PROCESS_VALIDATION_ENABLED, deploymentBuilder.isProcessValidationEnabled());
// Actually deploy
//执行真正的部署操作
commandContext.getProcessEngineConfiguration().getDeploymentManager().deploy(deployment, deploymentSettings);
if (deploymentBuilder.getProcessDefinitionsActivationDate() != null) {//流程定义是否有激活日期
scheduleProcessDefinitionActivation(commandContext, deployment);//进行流程定义的挂起或定时激活
}
if (commandContext.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {//默认开启
//触发entity被初始化事件
commandContext.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_INITIALIZED, deployment));
}
return deployment;
}
主要做的操作:
1、获取部署对象设置部署时间
2、在部署时会检测已部署的相同文件的最后一条记录,如果内容相同,则不会部署
查到且和要部署的一致,则直接返回查出来的
否则:
2.1 设置为一个新的定义
2.2 插入ACT_RE_DEPLOYMENT表(1条)和ACT_GE_BYTEARRAY表(png和bpmn定义)
2.3设置bpmn2.0检查开启,process流程定义检查开启
3、执行真正的部署
4、流程定义是否有激活日期,有则进行流程定义的挂起或定时激活
分析部署代码:
commandContext.getProcessEngineConfiguration().getDeploymentManager().deploy(deployment, deploymentSettings);
在deploymentManager里调用了BpmnDeployer的deploy方法。查看BpmnDeployer的deploy方法://真正的流程部署
@Override
public void deploy(DeploymentEntity deployment, Map<String, Object> deploymentSettings) {
log.debug("Processing deployment {}", deployment.getName());
// The ParsedDeployment represents the deployment, the process definitions, and the BPMN
// resource, parse, and model associated with each process definition.
ParsedDeployment parsedDeployment = parsedDeploymentBuilderFactory
.getBuilderForDeploymentAndSettings(deployment, deploymentSettings)
.build();
//校验文件里的多个流程定义不能出现多个同样的key
bpmnDeploymentHelper.verifyProcessDefinitionsDoNotShareKeys(parsedDeployment.getAllProcessDefinitions());
//通过deployment为流程定义赋更多属性(引擎版本、tenantId、deploymentId)
bpmnDeploymentHelper.copyDeploymentValuesToProcessDefinitions(
parsedDeployment.getDeployment(), parsedDeployment.getAllProcessDefinitions());
//为流程定义设置资源名称
bpmnDeploymentHelper.setResourceNamesOnProcessDefinitions(parsedDeployment);
//判断是否需要生成图片
createAndPersistNewDiagramsIfNeeded(parsedDeployment);
//为定义设置图片资源名称
setProcessDefinitionDiagramNames(parsedDeployment);
if (deployment.isNew()) {//新的
//查是否存在老的并放入map返回(new:old)
Map<ProcessDefinitionEntity, ProcessDefinitionEntity> mapOfNewProcessDefinitionToPreviousVersion =
getPreviousVersionsOfProcessDefinitions(parsedDeployment);
//给流程定义初始化流程定义id,设置版本号为1或者(根据是否有旧的版本号+1)
setProcessDefinitionVersionsAndIds(parsedDeployment, mapOfNewProcessDefinitionToPreviousVersion);
//流程定义入库,并给流程定义设置候选人也入库
persistProcessDefinitionsAndAuthorizations(parsedDeployment);
//取消旧的消息、信号、定时启动事件等及删库,且入库新的并绑定对应事件
updateTimersAndEvents(parsedDeployment, mapOfNewProcessDefinitionToPreviousVersion);
dispatchProcessDefinitionEntityInitializedEvent(parsedDeployment);//触发流程定义被初始化事件
} else {
//不是新的,则查出来的旧的,并给当前定义设置相关属性(貌似可用于更新(因为版本号没有增加))
makeProcessDefinitionsConsistentWithPersistedVersions(parsedDeployment);
}
//缓存操作:流程定义放入全局流程定义缓存map和全局流程定义treeNode缓存map,
//还有一个deployedArtifacts部署记录map(class org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl:实例list)
cachingAndArtifactsManager.updateCachingAndArtifacts(parsedDeployment);
for (ProcessDefinitionEntity processDefinition : parsedDeployment.getAllProcessDefinitions()) {
BpmnModel bpmnModel = parsedDeployment.getBpmnModelForProcessDefinition(processDefinition);
//更新流程定义中国际化数据
createLocalizationValues(processDefinition.getId(), bpmnModel.getProcessById(processDefinition.getKey()));
}
}
可以看出主要执行的操作:
1、进行了bpmn xml的解析和构建并保存在ParsedDeployment对象里:
该类相关数据结构:
protected DeploymentEntity deploymentEntity;
protected List<ProcessDefinitionEntity> processDefinitions;
protected Map<ProcessDefinitionEntity, BpmnParse> mapProcessDefinitionsToParses;
protected Map<ProcessDefinitionEntity, ResourceEntity> mapProcessDefinitionsToResources;
2、校验文件里的多个流程定义不能出现多个同样的key
3、通过deployment为流程定义赋更多属性(引擎版本、tenantId、deploymentId)
4、为流程定义设置资源名称
5、判断是否需要生成图片,不存在则创建diagram(入库ACT_GE_BYTEARRAY)
6、为定义设置图片资源名称
7、isNew是否为创建新的:
是:
7.1 查是否存在老的定义并放入map返回(new:old)
7.2 给流程定义初始化流程定义id,设置版本号为1或者(根据是否有旧的版本号+1)
7.3 流程定义入库,并给流程定义设置候选人也入库(流程定义入库ACT_RE_PROCDEF表;
流程启动候选人组入库ACT_RU_IDENTITYLINK:
getCandidateStarterUsers\getCandidateStarterGroups)
7.4 取消旧的消息、信号、定时启动事件等及删库,且入库新的并绑定对应事件
(ACT_RU_EVENT_SUBSCR,ACT_RU_TIMER_JOB)
7.5 触发流程定义被初始化事件
否:
7.1 不是新的,则查出来的旧的,并给当前定义设置相关属性(貌似可用于更新(因为版本号没有增加))
8、缓存操作:流程定义放入全局流程定义缓存map和全局流程定义treeNode缓存map,
//还有一个deployedArtifacts部署记录map(class org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntityImpl:实例list)
DeploymentCache<ProcessDefinitionCacheEntry>
ProcessDefinitionInfoCache
Map<Class<?>, List<Object>> deployedArtifacts;
9、更新所有流程定义中的国际化数据
相关说明:
//查找localization下语言为es的下id为id下属性为name
//例如结构{"localization":{"es":{"id1":{"name":"123"}}}} 返回"123"
JsonNode localizationNode = infoNode.path("localization").path(language).path(id).path(propertyName);
上面国际化数据通过查询ACT_PROCDEF_INFO表
Activiti社区交流群:839915498