activiti学习(十九)——流程虚拟机源码分析(一)——流程启动源码分析

从这篇文章开始,将从源码分析流程虚拟机的运转情况。本文主要讲讲流程启动相关的。流程虚拟机的调用与运转,跟前面对象解析器解析与设置是息息相关的。我看代码的时候,也常常需要来回翻阅对象解析器的设置。流程虚拟机在调用某个对象时,这个对象到底是什么,常常让我感到困惑。所以我决定一步一步进行梳理。

 

流程启动入口

 上图是调用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判断的分支环节,主要因为我对这些分支的了解也不够透彻,而且与流程启动这里也无关,所以暂时不作探讨。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值