服务热线
135-6963-3175
节点是怎么流转出线的呢?
主要做的操作: 主要做了如下操作: 检查是否补偿节点, 是: 1.到这里停止执行,做清理操作并返回。 否: 1.离开当前活动时候,要删除任务相关的执行(例如活动边界事件); if. 当是一个父元素而非流程实例时候:则先销毁该元素范围内的,通过:Context.getAgenda().planDestroyScopeOperation(execution); else 若是一个任务节点:更新(ACT_HI_ACTINST表)实例历史数据并删除子执行的相关数据(但不删除定义了边界取消事件的节点) 删除的子执行的数据有: 1.删除ACT_RU_IDENTITYLINK 2.删除ACT_RU_VARIABLE 3.删除ACT_GE_BYTEARRAY 4.删除ACT_RU_EXECUTION 2.判断节点类型 若是个节点:执行handleFlowNode操作: a.记录结束时间等信息及监听器的触发 b.若是特别子流程: 1.如果有完成条件、判断条件是否满足 2.若出线大于0则:执行出线leaveFlowNode() 出线为0则:执行删除执行相关数据操作(也就是可能是特殊子流程的最后一个节点了) 3.若1满足完成条件: 判断: 若特殊子流程不取消剩余实例: a.判断是否结束特殊子流程: 查找是否还有其他的子执行,若是则不结束; b.若结束则:Context.getAgenda().planEndExecutionOperation(execution.getParent()); 否则:leaveFlowNode操作: 1.获取默认序列流(如果设置) 2.获取所有出线的表达式并计算(两种情况:未开启跳过则进行表达式计算;1条出线或配置必须跳过条件为true) 3.确定哪些序列流可用于离开。 4.步骤2结果数为0且需计算条件(则从该节点所有出线里找出默认出线); 5.没有发现出线。结束执行。(Context.getAgenda().planEndExecutionOperation(execution节点)) 否则:从集合获取第一条线设置active为true。 并对所有出线创建子执行execution,并对所有子执行进行:Context.getAgenda().planContinueProcessOperation(outgoingExecution线)操作。 若是个线条:执行handleSequenceFlow操作。 1.更新结束信息(结束时间、花费时间、删除原因) 2.执行继续流程计划Context.getAgenda().planContinueProcessOperation(execution线);
貌似发现在TakeOutgoingSequenceFlowsOperation调用planContinueProcessOperation(execution线)参数都是seq线。
我们可以看TakeOutgoingSequenceFlowsOperation类的代码:
@Override public void run() { //要出线的元素 FlowElement currentFlowElement = getCurrentFlowElement(execution); // Compensation check 补偿检查 if ((currentFlowElement instanceof Activity) && ( ((Activity) currentFlowElement)).isForCompensation()) {//任务节点的补偿检查 /* 如果当前流程元素是补偿的一部分,我们并不总是希望遵循离开活动的常规规则。 更具体地说,如果没有传出序列流,我们只需在那里停止执行,而不是像我们通常做的那样在范围内找到传出序列流 * If the current flow element is part of a compensation, we don't always * want to follow the regular rules of leaving an activity. * More specifically, if there are no outgoing sequenceflow, we simply must stop * the execution there and don't go up in the scopes as we usually do * to find the outgoing sequenceflow */ cleanupCompensation(); return; } //当离开当前活动时,我们需要删除任何相关的执行(例如活动边界事件) //When leaving the current activity, we need to delete any related execution (eg active boundary events) cleanupExecutions(currentFlowElement); if (currentFlowElement instanceof FlowNode) {//当前元素是个节点 handleFlowNode((FlowNode) currentFlowElement); } else if (currentFlowElement instanceof SequenceFlow) { handleSequenceFlow(); } }
主要做了如下操作:
检查是否补偿节点:
是:的话则到这里停止执行,做清理操作并返回
否:1、离开当前活动时候,要删除任务相关的执行(例如活动边界事件)
2、若是个节点:执行handleFlowNode操作
若是个线条:执行handleSequenceFlow操作。
我们首先来分析步骤2源码:cleanupExecutions(currentFlowElement);
protected void cleanupExecutions(FlowElement currentFlowElement) { if (execution.getParentId() != null && execution.isScope()) { // If the execution is a scope (and not a process instance), the scope must first be // destroyed before we can continue and follow the sequence flow //如果执行是一个范围(而不是流程实例),则必须首先销毁该范围,然后我们才能继续并遵循序列流 Context.getAgenda().planDestroyScopeOperation(execution); } else if (currentFlowElement instanceof Activity) {//当是一个任务节点 // If the current activity is an activity, we need to remove any currently active boundary events Activity activity = (Activity) currentFlowElement; if (CollectionUtil.isNotEmpty(activity.getBoundaryEvents())) { // Cancel events are not removed List<String> notToDeleteEvents = new ArrayList<String>(); for (BoundaryEvent event : activity.getBoundaryEvents()) { if (CollectionUtil.isNotEmpty(event.getEventDefinitions()) && event.getEventDefinitions().get(0) instanceof CancelEventDefinition) { notToDeleteEvents.add(event.getId());//边界取消事件定义 } } // Delete all child executions Collection<ExecutionEntity> childExecutions = commandContext.getExecutionEntityManager().findChildExecutionsByParentExecutionId(execution.getId()); for (ExecutionEntity childExecution : childExecutions) { if (childExecution.getCurrentFlowElement() == null || !notToDeleteEvents.contains(childExecution.getCurrentFlowElement().getId())) { commandContext.getExecutionEntityManager().deleteExecutionAndRelatedData(childExecution, null, false); } } } } }
可以看到:
if. 当是一个父元素而非流程实例时候:则先销毁该元素范围内的,通过:Context.getAgenda().planDestroyScopeOperation(execution);
else 若是一个任务节点:更新(ACT_HI_ACTINST表)实例历史数据并删除子执行的相关数据(但不删除定义了边界取消事件的节点)
删除的子执行的数据有:
1.删除ACT_RU_IDENTITYLINK
2.删除ACT_RU_VARIABLE
3.删除ACT_GE_BYTEARRAY
4.删除ACT_RU_EXECUTION
接下来分析步骤3:
handleFlowNode((FlowNode) currentFlowElement);
protected void handleFlowNode(FlowNode flowNode) { handleActivityEnd(flowNode);//记录结束时间等信息及监听器的触发 if (flowNode.getParentContainer() != null && flowNode.getParentContainer() instanceof AdhocSubProcess) {//特别子流程 handleAdhocSubProcess(flowNode); } else { leaveFlowNode(flowNode); } }
代码主要操作:
1、记录结束时间等信息及监听器的触发
2、若是特别子流程则处理
否则:离开节点
特别子流程处理:
protected void handleAdhocSubProcess(FlowNode flowNode) { boolean completeAdhocSubProcess = false; AdhocSubProcess adhocSubProcess = (AdhocSubProcess) flowNode.getParentContainer(); if (adhocSubProcess.getCompletionCondition() != null) { Expression expression = Context.getProcessEngineConfiguration().getExpressionManager().createExpression(adhocSubProcess.getCompletionCondition()); Condition condition = new UelExpressionCondition(expression); if (condition.evaluate(adhocSubProcess.getId(), execution)) {//条件判断 completeAdhocSubProcess = true; } } if (flowNode.getOutgoingFlows().size() > 0) { leaveFlowNode(flowNode); } else { commandContext.getExecutionEntityManager().deleteExecutionAndRelatedData(execution, null, false); } if (completeAdhocSubProcess) {//完成 boolean endAdhocSubProcess = true; if (adhocSubProcess.isCancelRemainingInstances() == false) {//不取消剩余实例 List<ExecutionEntity> childExecutions = commandContext.getExecutionEntityManager().findChildExecutionsByParentExecutionId(execution.getParentId()); for (ExecutionEntity executionEntity : childExecutions) { if (executionEntity.getId().equals(execution.getId()) == false) { endAdhocSubProcess = false; break; } } } if (endAdhocSubProcess) {//结束特殊子流程 Context.getAgenda().planEndExecutionOperation(execution.getParent()); } } }
主要操作
如果有完成条件、判断条件是否满足
若出线大于0则执行出线leaveFlowNode()
出线为0则:执行删除执行相关数据操作(也就是可能是特殊子流程的最后一个节点了)
若满足完成条件:
判断:
若特殊子流程不取消剩余实例:
判断是否结束特殊子流程: 查找是否还有其他的子执行,若是则不结束;
若结束则:Context.getAgenda().planEndExecutionOperation(execution.getParent());
接下来分析leaveFlowNode(flowNode):
protected void leaveFlowNode(FlowNode flowNode) { logger.debug("Leaving flow node {} with id '{}' by following it's {} outgoing sequenceflow", flowNode.getClass(), flowNode.getId(), flowNode.getOutgoingFlows().size()); // Get default sequence flow (if set) //获取默认序列流(如果设置) String defaultSequenceFlowId = null; if (flowNode instanceof Activity) { defaultSequenceFlowId = ((Activity) flowNode).getDefaultFlow(); } else if (flowNode instanceof Gateway) { defaultSequenceFlowId = ((Gateway) flowNode).getDefaultFlow(); } // Determine which sequence flows can be used for leaving //确定哪些序列流可用于离开 List<SequenceFlow> outgoingSequenceFlows = new ArrayList<SequenceFlow>(); for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) {//获取所有出线的表达式并计算 //获取跳过表达式 String skipExpressionString = sequenceFlow.getSkipExpression(); //_ACTIVITI_SKIP_EXPRESSION_ENABLED全局变量是否开启跳过表达式 if (!SkipExpressionUtil.isSkipExpressionEnabled(execution, skipExpressionString)) {//未开启跳过表达式则计算 //忽略计算条件(false)或者(条件表达式计算为true且(默认出现为null或非默认出线)) if (!evaluateConditions || (evaluateConditions && ConditionUtil.hasTrueCondition(sequenceFlow, execution) && (defaultSequenceFlowId == null || !defaultSequenceFlowId.equals(sequenceFlow.getId())))) { outgoingSequenceFlows.add(sequenceFlow); } } else if (flowNode.getOutgoingFlows().size() == 1 || //1条出线或配置必须跳过条件为true SkipExpressionUtil.shouldSkipFlowElement(commandContext, execution, skipExpressionString)) { // The 'skip' for a sequence flow means that we skip the condition, not the sequence flow. //序列流的“跳过”意味着我们跳过条件,而不是序列流。 //出线为1或者计算应该跳过流元素 outgoingSequenceFlows.add(sequenceFlow); } } // Check if there is a default sequence flow 检查是否有默认的序列流,默认的加入出线集合 //出线为0且需计算条件(找出默认出线) if (outgoingSequenceFlows.size() == 0 && evaluateConditions) { // The elements that set this to false also have no support for default sequence flow if (defaultSequenceFlowId != null) { for (SequenceFlow sequenceFlow : flowNode.getOutgoingFlows()) { if (defaultSequenceFlowId.equals(sequenceFlow.getId())) { outgoingSequenceFlows.add(sequenceFlow); break; } } } } // No outgoing found. Ending the execution 没有发现出线。结束执行 if (outgoingSequenceFlows.size() == 0) { if (flowNode.getOutgoingFlows() == null || flowNode.getOutgoingFlows().size() == 0) { logger.debug("No outgoing sequence flow found for flow node '{}'.", flowNode.getId()); Context.getAgenda().planEndExecutionOperation(execution); } else { throw new ActivitiException("No outgoing sequence flow of element '" + flowNode.getId() + "' could be selected for continuing the process"); } } else { // Leave, and reuse the incoming sequence flow, make executions for all the others (if applicable) ExecutionEntityManager executionEntityManager = commandContext.getExecutionEntityManager(); List<ExecutionEntity> outgoingExecutions = new ArrayList<ExecutionEntity>(flowNode.getOutgoingFlows().size()); //获取第一条线 SequenceFlow sequenceFlow = outgoingSequenceFlows.get(0); // Reuse existing one execution.setCurrentFlowElement(sequenceFlow); execution.setActive(true); outgoingExecutions.add((ExecutionEntity) execution); // Executions for all the other one if (outgoingSequenceFlows.size() > 1) { for (int i = 1; i < outgoingSequenceFlows.size(); i++) { ExecutionEntity parent = execution.getParentId() != null ? execution.getParent() : execution; //大于一个出线,则为所有的出线入库(并行网关等...) ExecutionEntity outgoingExecutionEntity = commandContext.getExecutionEntityManager().createChildExecution(parent); SequenceFlow outgoingSequenceFlow = outgoingSequenceFlows.get(i); outgoingExecutionEntity.setCurrentFlowElement(outgoingSequenceFlow); executionEntityManager.insert(outgoingExecutionEntity); outgoingExecutions.add(outgoingExecutionEntity); } } // Leave (only done when all executions have been made, since some queries depend on this) 离开(仅在所有执行完成后才完成,因为某些查询依赖于此) for (ExecutionEntity outgoingExecution : outgoingExecutions) { Context.getAgenda().planContinueProcessOperation(outgoingExecution); } } }
分析代码,主要执行的操作:
获取默认序列流(如果设置)
获取所有出线的表达式并计算(两种情况:未开启跳过则进行表达式计算;1条出线或配置必须跳过条件为true)
确定哪些序列流可用于离开。
步骤2结果数为0且需计算条件(则从该节点所有出线里找出默认出线);
没有发现出线。结束执行。(Context.getAgenda().planEndExecutionOperation(execution节点))
否则:从集合获取第一条线设置active为true。
并对所有出线创建子执行execution,并对所有子执行进行: Context.getAgenda().planContinueProcessOperation(outgoingExecution线)操作。
分析步骤3handleSequenceFlow()方法:
protected void handleSequenceFlow() { commandContext.getHistoryManager().recordActivityEnd(execution, null); Context.getAgenda().planContinueProcessOperation(execution); }
主要进行操作:
1.更新结束信息(结束时间、花费时间、删除原因)
2.执行继续流程计划Context.getAgenda().planContinueProcessOperation(execution);