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爲自動跳過表達式。

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