从这篇文章开始,将从源码分析流程虚拟机的运转情况。本文主要讲讲流程启动相关的。流程虚拟机的调用与运转,跟前面对象解析器解析与设置是息息相关的。我看代码的时候,也常常需要来回翻阅对象解析器的设置。流程虚拟机在调用某个对象时,这个对象到底是什么,常常让我感到困惑。所以我决定一步一步进行梳理。
流程启动入口
上图是调用RuntimeService的startProcessInstanceById方法开始启动流程的活动图。首先通过传入的参数获取部署时生成的流程定义,通过流程定义生成执行实体类,并且设置流程变量,该ExecutionEntity即对应数据库ACT_RU_EXECUTION表。第10步通过原子操作类开始流程虚拟机的运转。第10步涉及的内容比较多,后面再详细叙述。
下面来看源码,从RuntimeService调用startProcessInstanceById,执行StartProcessInstanceCmd的execution方法开始:
public class StartProcessInstanceCmd<T> implements Command<ProcessInstance>, Serializable {
//......
public ProcessInstance execute(CommandContext commandContext) {
DeploymentManager deploymentManager = commandContext
.getProcessEngineConfiguration()
.getDeploymentManager();
ProcessDefinitionEntity processDefinition = null;
if (processDefinitionId != null) {
processDefinition = deploymentManager.findDeployedProcessDefinitionById(processDefinitionId);
if (processDefinition == null) {
throw new ActivitiObjectNotFoundException("No process definition found for id = '" + processDefinitionId + "'", ProcessDefinition.class);
}
} else if {
//......其他方法获取流程定义
} else {
throw new ActivitiIllegalArgumentException("processDefinitionKey and processDefinitionId are null");
}
//......
ExecutionEntity processInstance = processDefinition.createProcessInstance(businessKey);
initializeVariables(processInstance);
if (processInstanceName != null) {
processInstance.setName(processInstanceName);
commandContext.getHistoryManager().recordProcessInstanceNameChange(processInstance.getId(), processInstanceName);
}
processInstance.start();
return processInstance;
}
6-8行获取部署管理类。10-21行根据流程定义id获取部署流程图时生成的流程定义。23行创建执行实体类。24行为执行实体类设置流程变量。31行开始执行实体类。
接着看23行如何创建执行实体类,跟踪ProcessDefinitionEntity类:
public class ProcessDefinitionEntity extends ProcessDefinitionImpl implements ProcessDefinition, PersistentObject, HasRevision {
//......
public ExecutionEntity createProcessInstance(String businessKey, ActivityImpl initial) {
ExecutionEntity processInstance = null;
if(initial == null) {
processInstance = (ExecutionEntity) super.createProcessInstance();
}else {
processInstance = (ExecutionEntity) super.createProcessInstanceForInitial(initial);
}
//processInstances属性设置
Context.getCommandContext().getHistoryManager()
.recordProcessInstanceStart(processInstance);
if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityEvent(ActivitiEventType.ENTITY_CREATED, processInstance));
}
return processInstance;
}
public ExecutionEntity createProcessInstance(String businessKey) {
return createProcessInstance(businessKey, null);
}
//......
}
首先会调用29行的createProcessInstance,然后到第5行。启动时我们的initial为null,因此调用第9行。14-22的代码包括属性设置、触发全局事件转发、历史表记录等。第5行调用了超类ProcessDefinitionImpl的createProcessInstance方法,下面跟踪ProcessDefinitionImpl类:
public class ProcessDefinitionImpl extends ScopeImpl implements PvmProcessDefinition {
protected ActivityImpl initial;
//......
public PvmProcessInstance createProcessInstance() {
if(initial == null) {
//抛出异常
}
return createProcessInstanceForInitial(initial);
}
public PvmProcessInstance createProcessInstanceForInitial(ActivityImpl initial) {
if(initial == null) {
throw new ActivitiException("Cannot start process instance, initial activity where the process instance should start is null.");
}
InterpretableExecution processInstance = newProcessInstance(initial);
processInstance.setProcessDefinition(this);
processInstance.setProcessInstance(processInstance);
processInstance.initialize();
InterpretableExecution scopeInstance = processInstance;
List<ActivityImpl> initialActivityStack = getInitialActivityStack(initial);
for (ActivityImpl initialActivity: initialActivityStack) {
if (initialActivity.isScope()) {
scopeInstance = (InterpretableExecution) scopeInstance.createExecution();
scopeInstance.setActivity(initialActivity);
if (initialActivity.isScope()) {
scopeInstance.initialize();
}
}
}
scopeInstance.setActivity(initial);
return processInstance;
}
//......
}
进来第6行的createProcessInstance方法。第7行判断的initial是在对象解析阶段设置的startEvent,不了解的同学可以查阅StartEventParseHandler类的executeParse方法中调用的selectInitial。第7行的判断如果流程开始不存在startEvent那么流程就无法开始了,只能抛出异常。19行调用newProcessInstance,注意这里用到了多态,实际上调用的是ProcessDefinitionEntity的newProcessInstance方法创建ExecutionEntity,而不是调用ProcessDefinitionImpl的newProcessInstance创建ExecutionImpl。26行把startEvent保存到initialActivityStack中,方便管理。38行执行实体类当前的活动为startEvent。
到此为止,上面一系列的操作成功创建了执行实体类,并设置了当前活动为startEvent。下一步的工作是通过原子操作类使流程虚拟机运转起来,并执行startEvent的“行为”。
流程实例启动
在StartProcessInstanceCmd的execution最后,代码执行processInstance.start()启动流程实例,此时跳到ExecutionEntity的start方法
public class ExecutionEntity extends VariableScopeImpl implements ActivityExecution, ExecutionListenerExecution, Execution, PvmExecution,
ProcessInstance, InterpretableExecution, PersistentObject, HasRevision {
//......
public void start() {
if(startingExecution == null && isProcessInstanceType()) {
startingExecution = new StartingExecution(processDefinition.getInitial());
}
performOperation(AtomicOperation.PROCESS_START);
}
public void performOperation(AtomicOperation executionOperation) {
if (executionOperation.isAsync(this)) {
scheduleAtomicOperationAsync(executionOperation);
} else {
performOperationSync(executionOperation);
}
}
protected void performOperationSync(AtomicOperation executionOperation) {
Context
.getCommandContext()
.performOperation(executionOperation, this);
}
//......
}
第10行执行performOperation,参数是AtomicOperation.PROCESS_START,这属于原子类操作,我们一会讲。接着调用13-19行,根据流程文档里面设置的,判断是异步执行还是同步执行,这里我们先按同步执行去跟踪。紧接着调用CommandContext的performOperation方法。
public class CommandContext {
//......
public void performOperation(AtomicOperation executionOperation, InterpretableExecution execution) {
nextOperations.add(executionOperation);
if (nextOperations.size()==1) {
try {
Context.setExecutionContext(execution);
while (!nextOperations.isEmpty()) {
AtomicOperation currentOperation = nextOperations.removeFirst();
if (log.isTraceEnabled()) {
log.trace("AtomicOperation: {} on {}", currentOperation, this);
}
if (execution.getReplacedBy() == null) {
currentOperation.execute(execution);
} else {
currentOperation.execute(execution.getReplacedBy());
}
}
} finally {
Context.removeExecutionContext();
}
}
}
//......
}
上面代码逻辑很清晰,只要nextOperations中只有一个元素,则最终都会执行currentOperation.execute。这里的currentOperation.execute实际调用AbstractEventAtomicOperation的execute方法。接下来就是关于原子类了。
原子类调用
public interface AtomicOperation {
AtomicOperation PROCESS_START = new AtomicOperationProcessStart();
AtomicOperation PROCESS_START_INITIAL = new AtomicOperationProcessStartInitial();
AtomicOperation PROCESS_END = new AtomicOperationProcessEnd();
AtomicOperation ACTIVITY_START = new AtomicOperationActivityStart();
AtomicOperation ACTIVITY_EXECUTE = new AtomicOperationActivityExecute();
AtomicOperation ACTIVITY_END = new AtomicOperationActivityEnd();
AtomicOperation TRANSITION_NOTIFY_LISTENER_END = new AtomicOperationTransitionNotifyListenerEnd();
AtomicOperation TRANSITION_DESTROY_SCOPE = new AtomicOperationTransitionDestroyScope();
AtomicOperation TRANSITION_NOTIFY_LISTENER_TAKE = new AtomicOperationTransitionNotifyListenerTake();
AtomicOperation TRANSITION_CREATE_SCOPE = new AtomicOperationTransitionCreateScope();
AtomicOperation TRANSITION_NOTIFY_LISTENER_START = new AtomicOperationTransitionNotifyListenerStart();
AtomicOperation DELETE_CASCADE = new AtomicOperationDeleteCascade();
AtomicOperation DELETE_CASCADE_FIRE_ACTIVITY_END = new AtomicOperationDeleteCascadeFireActivityEnd();
void execute(InterpretableExecution execution);
boolean isAsync(InterpretableExecution execution);
}
上面是关于原子类顶层接口源码。其中PROCESS_START、PROCESS_START_INITIAL、ACTIVITY_START等等这些便是一个一个的原子类操作。原子类的架构等后面文章中再进行总结,因为涉及到整个流程运转好几个环节,待后面环节都分析了之后再总结好一些。
接着上一节的CommandContext的performOperation方法调用,最终我们会调用AbstractEventAtomicOperation的execute方法:
public abstract class AbstractEventAtomicOperation implements AtomicOperation {
//......
public void execute(InterpretableExecution execution) {
ScopeImpl scope = getScope(execution);
List<ExecutionListener> exectionListeners = scope.getExecutionListeners(getEventName());
int executionListenerIndex = execution.getExecutionListenerIndex();
if (exectionListeners.size()>executionListenerIndex) {
execution.setEventName(getEventName());
execution.setEventSource(scope);
ExecutionListener listener = exectionListeners.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);
eventNotificationsCompleted(execution);
}
}
}
这个函数主要是用于调用执行监听器的。每次调用,会触发一个执行监听器。第7行获取当前process的执行监听器集合,第8行获取当前执行的序号,第10行如果当前的序号大于执行监听器集合个数,即所有执行监听器已执行完毕,否则13行通过序号获取对应的执行监听器,15行触发执行监听器,21行执行监听器的序号加1,22行执行ExecutionEntity的performOperation方法,那又回到了我们流程实例启动时的调用。这样循环逐个调用执行监听器。当执行监听器都处理完毕之后,则29行调用eventNotificationsCompleted方法,由于多态的原因,这里会根据流程实例启动时ExecutionEntity的start方法中的performOperation(AtomicOperation.PROCESS_START)的参数,即调用AtomicOperationProcessStart的eventNotificationsCompleted方法。我们看下AtomicOperationProcessStart类:
public class AtomicOperationProcessStart extends AbstractEventAtomicOperation {
//......
protected void eventNotificationsCompleted(InterpretableExecution execution) {
if (Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Map<String, Object> variablesMap = null;
try {
variablesMap = execution.getVariables();
} catch (Throwable t) {
}
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createEntityWithVariablesEvent(ActivitiEventType.ENTITY_INITIALIZED,
execution, variablesMap, false));
Context.getProcessEngineConfiguration().getEventDispatcher()
.dispatchEvent(ActivitiEventBuilder.createProcessStartedEvent(execution, variablesMap, false));
}
ProcessDefinitionImpl processDefinition = execution.getProcessDefinition();
StartingExecution startingExecution = execution.getStartingExecution();
List<ActivityImpl> initialActivityStack = processDefinition.getInitialActivityStack(startingExecution.getInitial());
execution.setActivity(initialActivityStack.get(0));
execution.performOperation(PROCESS_START_INITIAL);
}
}
这里eventNotificationsCompleted的作用很简单,5-17行判断如果设置了全局事件转发器,则进行对应的事件转发。19-22行获取并设置execution当前的活动,当前的活动是startEvent。然后执行execution.performOperation,其调用的过程与流程启动时调用performOperation(AtomicOperation.PROCESS_START)过程类似。这里最终会调用AtomicOperationProcessStartInitial的eventNotificationsCompleted方法。我们看看AtomicOperationProcessStartInitial:
public class AtomicOperationProcessStartInitial extends AbstractEventAtomicOperation {
//......
protected void eventNotificationsCompleted(InterpretableExecution execution) {
ActivityImpl activity = (ActivityImpl) execution.getActivity();
ProcessDefinitionImpl processDefinition = execution.getProcessDefinition();
StartingExecution startingExecution = execution.getStartingExecution();
if (activity==startingExecution.getInitial()) {
execution.disposeStartingExecution();
execution.performOperation(ACTIVITY_EXECUTE);
} else {
List<ActivityImpl> initialActivityStack = processDefinition.getInitialActivityStack(startingExecution.getInitial());
int index = initialActivityStack.indexOf(activity);
activity = initialActivityStack.get(index+1);
InterpretableExecution executionToUse = null;
if (activity.isScope()) {
executionToUse = (InterpretableExecution) execution.getExecutions().get(0);
} else {
executionToUse = execution;
}
executionToUse.setActivity(activity);
executionToUse.performOperation(PROCESS_START_INITIAL);
}
}
}
由于在ExecutionEntity的start方法中,已经设置了startingExecution的selectedInitial属性为startEvent活动,因此第9行判断为真,执行execution.performOperation(ACTIVITY_EXECUTE)。即执行AtomicOperationActivityExecute的execute方法。来看AtomicOperationActivityExecute:
public class AtomicOperationActivityExecute implements AtomicOperation {
//......
public void execute(InterpretableExecution execution) {
ActivityImpl activity = (ActivityImpl) execution.getActivity();
ActivityBehavior activityBehavior = activity.getActivityBehavior();
if (activityBehavior==null) {
throw new PvmException("no behavior specified in "+activity);
}
try {
if(Context.getProcessEngineConfiguration() != null && Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
Context.getProcessEngineConfiguration().getEventDispatcher().dispatchEvent(
ActivitiEventBuilder.createActivityEvent(ActivitiEventType.ACTIVITY_STARTED,
execution.getActivity().getId(),
(String) execution.getActivity().getProperty("name"),
execution.getId(),
execution.getProcessInstanceId(),
execution.getProcessDefinitionId(),
(String) activity.getProperties().get("type"),
activity.getActivityBehavior().getClass().getCanonicalName()));
}
activityBehavior.execute(execution);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
LogMDC.putMDCExecution(execution);
throw new PvmException("couldn't execute activity <"+activity.getProperty("type")+" id=\""+activity.getId()+"\" ...>: "+e.getMessage(), e);
}
}
}
这个函数主要做两件事,第一件是15-23行转发ActivitiEventType.ACTIVITY_STARTED事件,第二件是26行调用startEvent设置的行为类。
行为类调用
在对象解析环节,startEvent设置的行为类是EventSubProcessStartEventActivityBehavior。行为类控制活动的行为。我们看看startEvent的行为是什么,EventSubProcessStartEventActivityBehavior:
public class EventSubProcessStartEventActivityBehavior extends NoneStartEventActivityBehavior {
//......
public void execute(ActivityExecution execution) throws Exception {
InterpretableExecution interpretableExecution = (InterpretableExecution) execution;
ActivityImpl activity = interpretableExecution.getProcessDefinition().findActivity(activityId);
ActivityExecution outgoingExecution = execution;
if(isInterrupting) {
execution.destroyScope("Event subprocess triggered using activity "+ activityId);
} else{
outgoingExecution = execution.createExecution();
outgoingExecution.setActive(true);
outgoingExecution.setScope(false);
outgoingExecution.setConcurrent(true);
}
((InterpretableExecution)outgoingExecution).setActivity(activity);
outgoingExecution.takeAll(activity.getOutgoingTransitions(), Collections.EMPTY_LIST);
}
}
第8行找出该行为对应的活动id,也就是startEvent的activityId。由于isInterrupting默认为true,因此走13行。第23行从startEvent的全部“出线”离开。至此,流程以从startEvent节点离开。
小结
流程虚拟机的调用非常繁琐,总结起来,首先客户端调用启动流程的命令类,接着创建执行实体类ExecutionEntity并调用其start方法开始启动,然后通过原子类调用执行监听器,之后调用流程的起点startEvent的活动类,最后活动类的处理方法是找到startEvent对应的ActivityImpl上的“出现”,并从全部“出现”离开。
这里代码解析略过了一些if else判断的分支环节,主要因为我对这些分支的了解也不够透彻,而且与流程启动这里也无关,所以暂时不作探讨。