activiti6.0 动态流程线,使用DMN实例.


必须要注意的是,DMN实例是单例设计模式,所以每一个流程版本只有一个实例. 在改变对象的时候相当于整个流程图实例都改变,但是实际上我们需要的只是流程实例改变而不是流程图实例改变.

所以在两个节点之间交换出路(OutgoingFlow)时需要上锁,以避免相同流程两个实例存在改变时出现问题.

删除的时候不能将原来的列表切换回去,只能移除元素,因为存在多并发时,做交换操作则会把其它的动态线干掉,所以只能删除操作.



1
/** 2 * 改变流程线元素列表. 3 * @param sourceFlowElement 4 * @param targetFlowElements 5 * @return 6 */ 7 private List<SequenceFlow> insideChangeOutgoingFlows(TaskInfo task, FlowElement sourceFlowElement, List<FlowElement> targetFlowElements) { 8 9 // 创建新的出路列表. 10 List<SequenceFlow> backupOutgoingFlows = new ArrayList<SequenceFlow>(); 11 List<SequenceFlow> newOutgoingFlows = new ArrayList<SequenceFlow>(); 12 // 注意需要引号. 并发条件下须要采用内部状态标识,否则会产生多实例或非预期结果. 原始flow条件中需要配置标识,当使用动态流程线,就不走原始流程线. 不使用并发就直接在改变流程线上层加入锁,一面出现意料以外结果. 13 String expression = "${" + CompleteTaskParam.TASKID + " == '" + task.getId() + "'}"; 14 15 for(FlowElement flowElement : targetFlowElements) { 16 // 构建新流程线 17 SequenceFlow newSequenceFlow = new SequenceFlow(); 18 // 源元素 19 newSequenceFlow.setSourceRef(sourceFlowElement.getId()); 20 newSequenceFlow.setSourceFlowElement(sourceFlowElement); 21 // 目标元素 22 newSequenceFlow.setTargetRef(flowElement.getId()); 23 newSequenceFlow.setTargetFlowElement(flowElement); 24 25 newSequenceFlow.setConditionExpression(expression); 26 backupOutgoingFlows.add(newSequenceFlow); 27 } 28 // 先将新流程线放置第一位. 29 newOutgoingFlows.addAll(backupOutgoingFlows); 30 31 synchronized (sourceFlowElement) { 32 // 转化为FlowNode对象才会有getOutgoingFlows和setOutgoingFlows 方法. 33 FlowNode flowNode = (FlowNode)sourceFlowElement; 34 // 取得流程节点的出路列表. 35 List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows(); 36 // 将原始流程线加入新出路列表 -- 不使用并发就需要去掉,并改变流程线上层加入锁 37 newOutgoingFlows.addAll(outgoingFlows); 38 // 替换源出路列表对象. 39 flowNode.setOutgoingFlows(newOutgoingFlows); 40 } 41 // 返回路对象. 用于后续清除流程线用. 42 return backupOutgoingFlows; 43 } 44 45 /** 46 * 删除流程线元素. 47 * @param sourceFlowElement 48 * @param sequenceFlows 49 */ 50 private void insideDeleteOutgoingFlows(FlowElement sourceFlowElement, List<SequenceFlow> sequenceFlows) { 51 // 转化为FlowNode对象才会有getOutgoingFlows和setOutgoingFlows 方法. 52 synchronized (sourceFlowElement) { 53 FlowNode flowNode = (FlowNode)sourceFlowElement; 54 List<SequenceFlow> outSequenceFlows = flowNode.getOutgoingFlows(); 55 List<SequenceFlow> newOutgoingFlows = new ArrayList<SequenceFlow>(); 56 newOutgoingFlows.addAll(outSequenceFlows); 57 newOutgoingFlows.removeAll(sequenceFlows); 58 // 替换源出路列表对象. 59 flowNode.setOutgoingFlows(newOutgoingFlows); 60 } 61 }

 

 如何获取DMN对象?

RepositoryService#getBpmnModel() 获取。

 

为什么没有出路和入路?

FlowNode的实例才会有。

 

FlowNode#getOutgoingFlows() 中的对象被改变会有影响吗?

分析源代码也没发现. 在使用过程中也没发现.

 

删除的时候为啥要上锁?

因为代码中使用的是iterator()进行循环的,改变列表会直接报错,所以在被其它线程引用的时候必须上锁.

 

posted @ 2021-02-05 10:46  Monato  阅读(562)  评论(0编辑  收藏  举报