activiti学习(十八)——流程虚拟机主要类的架构

想用activiti玩转中国式流程,单纯依靠普通的XXXService的api是不够的,必须要深入到数据库以及流程虚拟机的层面,修改数据库以及流程虚拟机对象,才能实现加签、减签、驳回、自由跳转之类的操作。另外,由于直接操作数据库很可能会有遗漏或者误操作,因此比较靠谱的方法是调用那些处于“中层”的api。“高层”的api就是XXXService的api,“底层”的是实体管理类的api。要熟悉这些“中层”api,需要看看源码中,activiti是如何调用这些api,这些api具体又做了什么。这样才能比较安全地处理这些中国式流程。

在《activiti学习(九)——对象解析器原理》中,其实已经对流程虚拟机有一个初步的探索。流程虚拟机,简单说就是按照规则,从起始点出发,通过连线解析后的对象TransitionImpl,走到指向的活动解析后的ActivityImpl,然后执行该ActivityImpl对应的行为。然后再离开这个ActivityImpl,通过TransitionImpl走到下一个ActivityImpl,然后执行其行为,如此类推。

本文主要分析流程虚拟机主要类的架构,即ActivityImpl、TransitionImpl以及它们的父类、接口的架构。本文比较适合一边研究流程虚拟机源码,一边对照着这些类和接口来看。我一开始看流程虚拟机,常常会看晕,搞不清楚具体在查什么,在执行什么,在调用什么。如果一开始看这些类的架构,可能也没什么特别的感觉。本文的作用是先对这些类有个大概的印象。

上图是流程虚拟机主要类的类图。上图看似挺复杂,下面我们分析一下主要的类及其作用,其实并不复杂。

 

PvmProcessElement接口:

public interface PvmProcessElement extends Serializable {
  String getId();
  PvmProcessDefinition getProcessDefinition();
  Object getProperty(String name);
}

PvmProcessElement接口是最顶层的接口。通过上述声明的方法可以看到,对于每个ActivityImpl和TransitionImpl,我们都可以getId方法获取其id,通过getProcessDefinition方法获取其所在流程的流程定义,通过getProperty获取其属性。

 

ProcessElementImpl类:

public class ProcessElementImpl implements PvmProcessElement {
  protected String id;
  protected ProcessDefinitionImpl processDefinition;
  protected Map<String, Object> properties;

  //......省略
}

ProcessElementImpl类是PvmProcessElement接口的具体实现。

 

ScopeImpl类:

public abstract class ScopeImpl extends ProcessElementImpl implements PvmScope {
  
  protected List<ActivityImpl> activities = new ArrayList<ActivityImpl>();
  protected Map<String, ActivityImpl> namedActivities = new HashMap<String, ActivityImpl>();
  protected Map<String, List<ExecutionListener>> executionListeners = new HashMap<String, List<ExecutionListener>>();
  protected IOSpecification ioSpecification;
  
  public ScopeImpl(String id, ProcessDefinitionImpl processDefinition) {
    super(id, processDefinition);
  }
  public ActivityImpl findActivity(String activityId) {
    //......
  }
  public ActivityImpl createActivity(String activityId) {
	//......
  }
  public boolean contains(ActivityImpl activity) {
    //......
  }
  public void addExecutionListener(String eventName, ExecutionListener executionListener, int index) {
   //......
  }

  //......
}

ScopeImpl是一个比较重要的类。上面的代码省略了很多。这个类的属性和方法大多涉及到Process这个元素。activities属性表示它包含的所有ActivityImpl。namedActivities属性是用于通过id找到对应ActivityImpl的Map,与findActivity方法相关。executionListeners是执行监听器的集合。ioSpecification属性与流程文档的DataInput、DataOutput相关。其中findActivity是我所说的“中层”api常会用到方法。

 

ProcessDefinitionImpl类:

public class ProcessDefinitionImpl extends ScopeImpl implements PvmProcessDefinition {

  protected String name;
  protected String key;
  protected String description;
  protected ActivityImpl initial;
  protected Map<ActivityImpl, List<ActivityImpl>> initialActivityStacks = new HashMap<ActivityImpl, List<ActivityImpl>>();
  protected List<LaneSet> laneSets;
  protected ParticipantProcess participantProcess;

  public ProcessDefinitionImpl(String id) {
    super(id, null);
    processDefinition = this;
  }

  public PvmProcessInstance createProcessInstance() {
    if(initial == null) {
      throw new ActivitiException("Process '"+name+"' has no default start activity (e.g. none start event), hence you cannot use 'startProcessInstanceBy...' but have to start it using one of the modeled start events (e.g. message start events).");
    }
    return createProcessInstanceForInitial(initial);
  }

  public PvmProcessInstance createProcessInstanceForInitial(ActivityImpl initial) {
    //......
  }
  
  public synchronized List<ActivityImpl> getInitialActivityStack(ActivityImpl startActivity) {
    //......
  }

  //......
}

ProcessElementImpl类中initial属性代表流程起始的活动,通常对应流程的startEvent。createProcessInstanceForInitial是启动流程时调用的方法。

 

ActivityImpl类:

public class ActivityImpl extends ScopeImpl implements PvmActivity, HasDIBounds {

  protected List<TransitionImpl> outgoingTransitions = new ArrayList<TransitionImpl>();
  protected Map<String, TransitionImpl> namedOutgoingTransitions = new HashMap<String, TransitionImpl>();
  protected Map<String, Object> variables;
  protected List<TransitionImpl> incomingTransitions = new ArrayList<TransitionImpl>();
  protected ActivityBehavior activityBehavior;
  protected ScopeImpl parent;
  protected boolean isScope;
  protected boolean isAsync;
  protected boolean isExclusive;
  protected String failedJobRetryTimeCycleValue;
  
  protected int x = -1;
  protected int y = -1;
  protected int width = -1;
  protected int height = -1;
  
  public ActivityImpl(String id, ProcessDefinitionImpl processDefinition) {
    super(id, processDefinition);
  }

  public TransitionImpl createOutgoingTransition(String transitionId, Expression skipExpression) {
//......
  }
  
  public TransitionImpl findOutgoingTransition(String transitionId) {
    return namedOutgoingTransitions.get(transitionId);
  }

//......
}

outgoingTransitions属性为从这个活动节点出去的线的集合,即“出线”的集合。namedOutgoingTransitions为一个根据“出线”的id为key、“出线”为value的map对象,方便快速找出对应“出线”。incomingTransitions为“进线”的集合。activityBehavior属性代表这个活动对应的“行为”。即流程运行到改节点时,节点会做什么,当用户调用某些方法时,节点又会进行什么处理。“行为”是activiti节点的核心。另外通过上面createOutgoingTransition、findOutgoingTransition方法可以看出,连线的对象是通过ActivityImpl进行创建的。

 

TransitionImpl类

public class TransitionImpl extends ProcessElementImpl implements PvmTransition {

  protected ActivityImpl source;
  protected ActivityImpl destination;
  protected List<ExecutionListener> executionListeners;
  protected Expression skipExpression;

//......
}

source属性为连线的起始节点,destination为连线的终止节点。executionListeners为执行监听器集合。skipExpression为自动跳过表达式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章