簡述
《activiti學習(十九)——流程虛擬機源碼分析(一)——流程啓動源碼分析》一文中最後,流程從startEvent節點執行takeAll準備離開。本文我們分析一下從開始節點到下一個節點之前虛擬機做了什麼。由於流程虛擬機條件分支情況很多,一一敘述非常繁瑣(有些我自己理解也不透徹),所以我會用最簡單的模型去跟蹤其流轉,如下圖:
我們假設起點startEvent的下一個節點是一個普通的userTask,本文跟蹤其在流程虛擬機的代碼走向。
跟蹤源碼
上一篇文章我們跟蹤到ExecutionEntity的takeAll方法。startEvent活動類通過調用這個方法離開startEvent節點。
public class ExecutionEntity extends VariableScopeImpl implements ActivityExecution, ExecutionListenerExecution, Execution, PvmExecution,
ProcessInstance, InterpretableExecution, PersistentObject, HasRevision {
//......
public void takeAll(List<PvmTransition> transitions, List<ActivityExecution> recyclableExecutions) {
fireActivityCompletedEvent();
transitions = new ArrayList<PvmTransition>(transitions);
recyclableExecutions = (recyclableExecutions!=null ? new ArrayList<ActivityExecution>(recyclableExecutions) : new ArrayList<ActivityExecution>());
if (recyclableExecutions.size()>1) {
for (ActivityExecution recyclableExecution: recyclableExecutions) {
if (((ExecutionEntity)recyclableExecution).isScope()) {
throw new PvmException("joining scope executions is not allowed");
}
}
}
ExecutionEntity concurrentRoot = ((isConcurrent && !isScope) ? getParent() : this);
List<ExecutionEntity> concurrentActiveExecutions = new ArrayList<ExecutionEntity>();
List<ExecutionEntity> concurrentInActiveExecutions = new ArrayList<ExecutionEntity>();
for (ExecutionEntity execution: concurrentRoot.getExecutions()) {
if (execution.isActive()) {
concurrentActiveExecutions.add(execution);
} else {
concurrentInActiveExecutions.add(execution);
}
}
if ( (transitions.size()==1)
&& (concurrentActiveExecutions.isEmpty())
&& allExecutionsInSameActivity(concurrentInActiveExecutions)
) {
List<ExecutionEntity> recyclableExecutionImpls = (List) recyclableExecutions;
recyclableExecutions.remove(concurrentRoot);
for (ExecutionEntity prunedExecution: recyclableExecutionImpls) {
Context.getCommandContext().getHistoryManager().recordActivityEnd(prunedExecution);
prunedExecution.remove();
}
concurrentRoot.setActive(true);
concurrentRoot.setActivity(activity);
concurrentRoot.setConcurrent(false);
concurrentRoot.take(transitions.get(0), false);
} else {
//......
}
public void take(PvmTransition transition, boolean fireActivityCompletionEvent) {
if (fireActivityCompletionEvent) {
fireActivityCompletedEvent();
}
if (this.transition!=null) {
throw new PvmException("already taking a transition");
}
if (transition==null) {
throw new PvmException("transition is null");
}
setActivity((ActivityImpl)transition.getSource());
setTransition((TransitionImpl) transition);
performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_END);
}
//......
}
第8行fireActivityCompletedEvent方法會觸發全局事件轉發器轉發ACTIVITY_COMPLETED事件。11行由於入參recyclableExecutions爲空,所以爲recyclableExecutions新建一個空的數組。22行isConcurrent默認爲false,isScope默認是true,因此concurrentRoot賦值爲this。32-34行判斷假設startEvent的“出線”只有一條,則此時判斷爲true。48行通過take離開startEvent節點。66行設置當前活動爲startEvent的ActivitiImpl,67行設置當前的連線,68行調用原子操作performOperation(AtomicOperation.TRANSITION_NOTIFY_LISTENER_END)。這個原子操作的調用我們上一篇文章分析過,這裏不再細述。看看AtomicOperation.TRANSITION_NOTIFY_LISTENER_END對應的AtomicOperationTransitionNotifyListenerEnd類:
public class AtomicOperationTransitionNotifyListenerEnd extends AbstractEventAtomicOperation {
//......
protected String getEventName() {
return org.activiti.engine.impl.pvm.PvmEvent.EVENTNAME_END;
}
protected void eventNotificationsCompleted(InterpretableExecution execution) {
execution.performOperation(TRANSITION_DESTROY_SCOPE);
}
}
這裏原子操作首先會觸發實行監聽器的end事件,然後執行原子操作performOperation(TRANSITION_DESTROY_SCOPE)。即調用AtomicOperationTransitionDestroyScope類
public class AtomicOperationTransitionDestroyScope implements AtomicOperation {
//......
@SuppressWarnings("unchecked")
public void execute(InterpretableExecution execution) {
InterpretableExecution propagatingExecution = null;
ActivityImpl activity = (ActivityImpl) execution.getActivity();
if (activity.isScope()) {
//......
} else {
propagatingExecution = execution;
}
ScopeImpl nextOuterScopeElement = activity.getParent();
TransitionImpl transition = propagatingExecution.getTransition();
ActivityImpl destination = transition.getDestination();
if (transitionLeavesNextOuterScope(nextOuterScopeElement, destination)) {
propagatingExecution.setActivity((ActivityImpl) nextOuterScopeElement);
propagatingExecution.performOperation(TRANSITION_NOTIFY_LISTENER_END);
} else {
propagatingExecution.performOperation(TRANSITION_NOTIFY_LISTENER_TAKE);
}
}
public boolean transitionLeavesNextOuterScope(ScopeImpl nextScopeElement, ActivityImpl destination) {
return !nextScopeElement.contains(destination);
}
}
執行execution方法,第10行的if判斷爲false,注意execution的isScope爲true,但是ActivityImpl的isScope爲false,所以這裏執行13行的代碼。16行獲取activity.getParent(),即startEvent的parent,是Process對象。18行獲取連線終點的活動。19行判斷Process中是否含有下一個節點的活動,因此28行函數判斷爲false(!符號取了相反的值),因此走23行performOperation(TRANSITION_NOTIFY_LISTENER_TAKE),會調用AtomicOperationTransitionNotifyListenerTake類。
public class AtomicOperationTransitionNotifyListenerTake implements AtomicOperation {
//......
public void execute(InterpretableExecution execution) {
TransitionImpl transition = execution.getTransition();
List<ExecutionListener> executionListeners = transition.getExecutionListeners();
int executionListenerIndex = execution.getExecutionListenerIndex();
if (executionListeners.size()>executionListenerIndex) {
execution.setEventName(org.activiti.engine.impl.pvm.PvmEvent.EVENTNAME_TAKE);
execution.setEventSource(transition);
ExecutionListener listener = executionListeners.get(executionListenerIndex);
try {
listener.notify(execution);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new PvmException("couldn't execute event listener : "+e.getMessage(), e);
}
execution.setExecutionListenerIndex(executionListenerIndex+1);
execution.performOperation(this);
} else {
execution.setExecutionListenerIndex(0);
execution.setEventName(null);
execution.setEventSource(null);
ActivityImpl activity = (ActivityImpl) execution.getActivity();
ActivityImpl nextScope = findNextScope(activity.getParent(), transition.getDestination());
execution.setActivity(nextScope);
if(Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createSequenceFlowTakenEvent(ActivitiEventType.SEQUENCEFLOW_TAKEN, transition.getId(),
activity.getId(), (String) activity.getProperties().get("name") ,(String) activity.getProperties().get("type"), activity.getActivityBehavior().getClass().getCanonicalName(),
nextScope.getId(), (String) nextScope.getProperties().get("name"), (String) nextScope.getProperties().get("type"), nextScope.getActivityBehavior().getClass().getCanonicalName()));
}
execution.performOperation(TRANSITION_CREATE_SCOPE);
}
}
/** finds the next scope to enter. the most outer scope is found first */
public static ActivityImpl findNextScope(ScopeImpl outerScopeElement, ActivityImpl destination) {
ActivityImpl nextScope = destination;
while( (nextScope.getParent() instanceof ActivityImpl)
&& (nextScope.getParent() != outerScopeElement)
) {
nextScope = (ActivityImpl) nextScope.getParent();
}
return nextScope;
}
}
8-23行嵌套調用,遍歷每一個執行監聽器觸發take事件。30-32行把execution的當前活動設置爲下一個活動節點。34-38行觸發全局事件轉發器SEQUENCEFLOW_TAKEN事件。從此execution進入下一個節點。
小結
普遍來說,流程從一般的活動離開,就是通過ExecutionEntity的take方法,然後經歷數個原子操作,觸發執行監聽器和全局事件轉發器對應的事件,如果涉及子流程、網關形成的分支流程等,則情況會更復雜一些。最後把該觸發的事件都觸發完畢之後,把ExecutionEntity當前的活動設置爲下一個節點,就此進入下一個節點相關的活動中。