服务热线
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()