服务热线
135-6963-3175
流程是怎么结束执行的呢?
此操作结束执行并遵循典型的 BPMN 规则以继续该流程。此操作通常不是通过 {@link ActivityBehavior} 行为安排的,
而是从另一个操作安排的。当条件使得流程无法通过常规方式继续并且需要进行执行清理时,就会发生这种情况,这可能会开辟继续流程实例的新方式。
1.节点出线为0时候
2.结束特殊子流程时候
3.清理补偿时候,实例类型结束执行
概要:
若是流程实例级别: 1.找父实例 存在父执行:在销毁结束的子流程实例(callActivity)之前保存变量。(通过调用父执行当前元素的行为类的completing方法) 2.获取存活的子执行数量 0:通过流程实例id删除实例相关数据(所有); 3.流程存在执行监听器则执行结束"end"执行监听器; 4.存在父执行,父执行实例的子流程实例设置为null,并通过调用父执行元素活动行为类的completed用于离开; 否: 1.如果执行是父但非流程实例:则必须首先删除所有子执行。 2.删除执行实例相关数据 3.多实例子流程中结束执行时:处理多实例子流程 4.如果没有更多活动的子执行,则流程可以继续(例如嵌入式子流程仍有活动元素,我们无法继续) a.在结束子流程的情况下: 是补偿:那么我们不需要做任何事情,可以结束它(planEndExecutionOperation(parentExecution)) 非补偿:处理子流程结束:handleSubProcessEnd() b.非子流程: 处理规则执行end:handleRegularExecutionEnd() c.若ab执行后executionToContinue: 不为空:(如果执行不是流程实例根执行,则仅继续传出序列流(否则流程实例已完成)) 流程实例类型:(handleProcessInstanceExecution(该方法上面已分析过)) 否则:planTakeOutgoingSequenceFlowsOperation()
我们可以看下EndExecutionOperationd类的核心代码:
@Override
public void run() {
if (execution.isProcessInstanceType()) {//流程实例级别
1.找父实例执行
存在父执行则:在销毁结束的子流程实例(调用活动)之前复制变量(用于保存内嵌子流程的变量到库和执行实例execution)
2.获取存活的子执行数量
注意这里使用流程实例执行来获取流程元素(删除实例相关数据(所有))
3.执行结束"end"监听器。(当节点的执行监听器集合不为空)
4.存在父执行:"离开操作"(AbstractBpmnActivityBehavior.leave())
handleProcessInstanceExecution(execution);
} else {
1.如果执行是父元素但非流程实例,则必须首先删除所有子执行。
2.删除当前执行
3. 在多实例子流程中结束执行时:
处理多实例子流程
4.如果没有更多活动的子执行,则流程可以继续(例如嵌入式子流程仍有活动元素,我们无法继续)
若当前元素有子流程:
补偿:则planEndExecutionOperation(parent)
否则:
handleRegularExecution();
}
}分析代码:
若是流程实例级别:执行handleProcessInstanceExecution(execution);方法
否则:执行handleRegularExecution();
我们首先来分析流程实例处理方法handleProcessInstanceExecution:
protected void handleProcessInstanceExecution(ExecutionEntity processInstanceExecution) {
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
String processInstanceId = processInstanceExecution.getId(); // No parent execution == process instance id
logger.debug("No parent execution found. Verifying if process instance {} can be stopped.", processInstanceId);
ExecutionEntity superExecution = processInstanceExecution.getSuperExecution();//找父实例
SubProcessActivityBehavior subProcessActivityBehavior = null;
//在销毁结束的子流程实例(调用活动)之前复制变量
// copy variables before destroying the ended sub process instance (call activity)
if (superExecution != null) {//存在父执行
FlowNode superExecutionElement = (FlowNode) superExecution.getCurrentFlowElement();
subProcessActivityBehavior = (SubProcessActivityBehavior) superExecutionElement.getBehavior();
try {
subProcessActivityBehavior.completing(superExecution, processInstanceExecution);//用于保存内嵌子流程的变量到库和执行实例execution
} catch (RuntimeException e) {
logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
throw e;
} catch (Exception e) {
logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
throw new ActivitiException("Error while completing sub process of execution " + processInstanceExecution, e);
}
}
//获取存活的子执行数量
int activeExecutions = getNumberOfActiveChildExecutionsForProcessInstance(executionEntityManager, processInstanceId);
if (activeExecutions == 0) {
logger.debug("No active executions found. Ending process instance {} ", processInstanceId);
//注意这里使用流程实例执行来获取流程元素(删除实例相关数据(所有))
// note the use of execution here vs processinstance execution for getting the flowelement
executionEntityManager.deleteProcessInstanceExecutionEntity(processInstanceId,
execution.getCurrentFlowElement() != null ? execution.getCurrentFlowElement().getId() : null, null, false, false);
} else {
logger.debug("Active executions found. Process instance {} will not be ended.", processInstanceId);
}
Process process = ProcessDefinitionUtil.getProcess(processInstanceExecution.getProcessDefinitionId());
// Execute execution listeners for process end. 执行结束监听器。
if (CollectionUtil.isNotEmpty(process.getExecutionListeners())) {
executeExecutionListeners(process, processInstanceExecution, ExecutionListener.EVENTNAME_END);//"end"
}
// and trigger execution afterwards if doing a call activity
if (superExecution != null) {
superExecution.setSubProcessInstance(null);
try {
subProcessActivityBehavior.completed(superExecution);//用于离开
} catch (RuntimeException e) {
logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
throw e;
} catch (Exception e) {
logger.error("Error while completing sub process of execution {}", processInstanceExecution, e);
throw new ActivitiException("Error while completing sub process of execution " + processInstanceExecution, e);
}
}
}分析代码,主要操作:
1.找父实例
存在父执行:在销毁结束的子流程实例(调用活动)之前保存变量。(通过调用父执行当前元素的行为类的completing方法)
2.获取存活的子执行数量
0:删除实例相关数据(所有),通过流程实例id;
3.流程存在执行监听器则执行结束"end"执行监听器;
4.存在父执行,父执行实例的子流程实例设置为null,并通过调用父执行元素活动行为类的completed用于离开
可以看下CallActivityBehavior行为类的completing方法:
public void completing(DelegateExecution execution, DelegateExecution subProcessInstance) throws Exception {
// only data. no control flow available on this execution.
ExpressionManager expressionManager = Context.getProcessEngineConfiguration().getExpressionManager();
// copy process variables
ExecutionEntity executionEntity = (ExecutionEntity) execution;
CallActivity callActivity = (CallActivity) executionEntity.getCurrentFlowElement();//活动调用
for (IOParameter ioParameter : callActivity.getOutParameters()) {//出参数
Object value = null;
if (StringUtils.isNotEmpty(ioParameter.getSourceExpression())) {//参数表达式计算值
Expression expression = expressionManager.createExpression(ioParameter.getSourceExpression().trim());
value = expression.getValue(subProcessInstance);
} else {
value = subProcessInstance.getVariable(ioParameter.getSource());
}
execution.setVariable(ioParameter.getTarget(), value);//设置变量
}
}发现该方法会获取活动的所有出参数并参与表达式计算,进行变量入库。
而CallActivityBehavior的completed方法:
public void completed(DelegateExecution execution) throws Exception {
// only control flow. no sub process instance data available 只控制流。没有可用的子流程实例数据
leave(execution);
}用于离开节点。
最终调用了父类AbstractBpmnActivityBehavior的leave方法:
public void leave(DelegateExecution execution) {
FlowElement currentFlowElement = execution.getCurrentFlowElement();
//查找该节点的边界事件
Collection<BoundaryEvent> boundaryEvents = findBoundaryEventsForFlowNode(execution.getProcessDefinitionId(), currentFlowElement);
if (CollectionUtil.isNotEmpty(boundaryEvents)) {
//执行边界事件
executeCompensateBoundaryEvents(boundaryEvents, execution);
}
if (!hasLoopCharacteristics()) {//没有多实例
super.leave(execution);
} else if (hasMultiInstanceCharacteristics()) {//执行多实例行为
multiInstanceActivityBehavior.leave(execution);
}
}后面调用了FlowNodeActivityBehavior的leave():
public void leave(DelegateExecution execution) {
//执行出线计算-执行默认传出行为
bpmnActivityBehavior.performDefaultOutgoingBehavior((ExecutionEntity) execution);
}
----最终通过Context.getAgenda().planTakeOutgoingSequenceFlowsOperation(execution, true);进行离开接下来我们分析handleRegularExecution():
protected void handleRegularExecution() {
ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager();
// There will be a parent execution (or else we would be in the process instance handling method)
ExecutionEntity parentExecution = executionEntityManager.findById(execution.getParentId());
// If the execution is a scope, all the child executions must be deleted first.
if (execution.isScope()) {//如果执行是父但非流程实例,则必须首先删除所有子执行。
executionEntityManager.deleteChildExecutions(execution, null, false);
}
// Delete current execution
logger.debug("Ending execution {}", execution.getId());
executionEntityManager.deleteExecutionAndRelatedData(execution, null, false);
logger.debug("Parent execution found. Continuing process using execution {}", parentExecution.getId());
// 需要特别注意: 在多实例子流程中结束执行时;
// When ending an execution in a multi instance subprocess , special care is needed
if (isEndEventInMultiInstanceSubprocess(execution)) {
handleMultiInstanceSubProcess(executionEntityManager, parentExecution);//处理多实例子流程
return;
}
SubProcess subProcess = execution.getCurrentFlowElement().getSubProcess();
// 如果没有更多活动的子执行,则流程可以继续(例如嵌入式子流程仍有活动元素,我们无法继续)
// If there are no more active child executions, the process can be continued
// If not (eg an embedded subprocess still has active elements, we cannot continue)
if (getNumberOfActiveChildExecutionsForExecution(executionEntityManager, parentExecution.getId()) == 0
|| isAllEventScopeExecutions(executionEntityManager, parentExecution)) {
ExecutionEntity executionToContinue = null;
if (subProcess != null) {
// 在结束子流程的情况下:进入范围并通过父范围继续,除非它是补偿,那么我们不需要做任何事情,可以结束它
// In case of ending a subprocess: go up in the scopes and continue via the parent scope
// unless its a compensation, then we don't need to do anything and can just end it
if (subProcess.isForCompensation()) {
Context.getAgenda().planEndExecutionOperation(parentExecution);
} else {
//处理子流程结束
executionToContinue = handleSubProcessEnd(executionEntityManager, parentExecution, subProcess);
}
} else {
// In the 'regular' case (not being in a subprocess), we use the parent execution to
// continue process instance execution
// 处理规则执行end
executionToContinue = handleRegularExecutionEnd(executionEntityManager, parentExecution);
}
if (executionToContinue != null) {
// 如果执行不是流程实例根执行,则仅继续传出序列流(否则流程实例已完成)
// only continue with outgoing sequence flows if the execution is
// not the process instance root execution (otherwise the process instance is finished)
if (executionToContinue.isProcessInstanceType()) {//流程实例类型
handleProcessInstanceExecution(executionToContinue);
} else {
Context.getAgenda().planTakeOutgoingSequenceFlowsOperation(executionToContinue, true);
}
}
}
}分析代码,做了操作:
如果执行是父但非流程实例,则必须首先删除所有子执行。
删除执行实例相关数据
多实例子流程中结束执行时:处理多实例子流程
如果没有更多活动的子执行,则流程可以继续(例如嵌入式子流程仍有活动元素,我们无法继续)
在结束子流程的情况下:
是补偿:那么我们不需要做任何事情,可以结束它(planEndExecutionOperation(parentExecution))
非补偿:处理子流程结束:handleSubProcessEnd()
非子流程:
处理规则执行end:handleRegularExecutionEnd()
c.若ab执行后executionToContinue:
不为空:(如果执行不是流程实例根执行,则仅继续传出序列流(否则流程实例已完成))
流程实例类型:(handleProcessInstanceExecution(该方法上面已分析过))
否则:planTakeOutgoingSequenceFlowsOperation()