activiti總體框架分析

Engine解析

activiti包.png

1. org.activiti.engine

  1. 定義了流程管理服務的接口:RepositoryService、RuntimeService、 FormService、TaskServiceHistoryService、IdentityService、 ManagementService 。
  • 定義了引擎配置管理接口ProcessEngineConfiguration

  • 定義了activiti異常類ActivitiException。

org.activiti.engine是activiti的核心功能,控制工作流的流轉。幾個核心的類如下圖所示:

engine

1.1 ProcessEngine

ProcessEngine接口繼承EngineServices,EngineServices包括很多工作流/BPM方法的服務,它們都是線程安全的。EngineServices提供的服務包括:

  • RepositoryService:提供了管理和控制流程定義的操作。

  • RuntimeService:提供了管理和控制流程實例的操作。

  • FormService:提供了管理流程表單的操作,即使不用FormService,activiti也可以完美運行。

  • TaskService:提供了任務管理的操作,包括實例任務掛起激活、完成、暫停查詢

  • HistoryService:提供對歷史流程,歷史任務,歷史變量的查詢操作。

  • IdentityService:提供用戶和組管理的操作(創建,更新,刪除,查詢...)。

  • ManagementService:提供了查詢和管理異步操作(定時器,異步操作, 延遲暫停、激活等)的功能,它還可以查詢到數據庫的表和表的元數據。

EngineServices 代碼如下所示:


  public interface EngineServices {

    RepositoryService getRepositoryService();

    RuntimeService getRuntimeService();

    FormService getFormService();

    TaskService getTaskService();

    HistoryService getHistoryService();

    IdentityService getIdentityService();

    ManagementService getManagementService();

    ProcessEngineConfiguration getProcessEngineConfiguration();
  }

ProcessEngine 代碼如下所示:


  public interface ProcessEngine extends EngineServices {

    /** the version of the activiti library */
    public static String VERSION = "5.17.0.2";

    /** The name as specified in 'process-engine-name' in
     * the activiti.cfg.xml configuration file.
     * The default name for a process engine is 'default */
    String getName();

    void close();
  }

1.2 ProcessEngineConfiguration

ProcessEngineConfiguration是配置管理類,它管理的對象包括ProcessEngine,XXservice,數據庫session等。ProcessEngineConfiguration的配置,activiti默認會從activiti.cfg.xml中讀取,也可以在Spring的配置文件中讀取。ProcessEngineConfiguration的實現包括:

  • ProcessEngineConfigurationImpl繼承ProcessEngineConfiguration,實現了各種Service的初始化

  • StandaloneProcessEngineConfiguration是單獨運行的流程引擎,繼承ProcessEngineConfigurationImpl。代碼如下:

  public class StandaloneProcessEngineConfiguration extends ProcessEngineConfigurationImpl {
    @Override
    protected CommandInterceptor createTransactionInterceptor() {
      return null;
    }
  }
  • StandaloneInMemProcessEngineConfiguration是單元測試時的輔助類,繼承StandaloneProcessEngineConfiguration,默認使用H2內存數據庫。數據庫表會在引擎啟動時創建,關閉時刪除。代碼如下所示:
  public class StandaloneInMemProcessEngineConfiguration extends StandaloneProcessEngineConfiguration {
   public StandaloneInMemProcessEngineConfiguration() {
     this.databaseSchemaUpdate = DB_SCHEMA_UPDATE_CREATE_DROP;
     this.jdbcUrl = "jdbc:h2:mem:activiti";
   }
  }
  • SpringProcessEngineConfiguration是Spring環境下使用的流程引擎。

  • JtaProcessEngineConfiguration單獨運行的流程引擎,并使用JTA事務。

1.3 ActivitiException

activiti的基礎異常類是org.activiti.engine.ActivitiException,一個非檢查異常。Activiti的異常都是通過org.activiti.engine.ActivitiException拋出,但存在以下特殊情況:

  • ActivitiWrongDbException:當Activiti引擎發現數據庫版本號和引擎版本號不一致時拋出。

  • ActivitiOptimisticLockingException:對同一數據進行并發方法并出現樂觀鎖時拋出。

  • ActivitiClassLoadingException:當無法找到需要加載的類或在加載類時出現了錯誤(比如,JavaDelegate,TaskListener等。

  • ActivitiObjectNotFoundException:當請求或操作的對應不存在時拋出。

  • ActivitiIllegalArgumentException:這個異常表示調用Activiti API時傳入了一個非法的參數,可能是引擎配置中的非法值,或提供了一個非法制,或流程定義中使用的非法值。

  • ActivitiTaskAlreadyClaimedException:當任務已經被認領了,再調用taskService.claim(...)就會拋出。

  • BpmnError:流程部署錯誤,如流程定義文件不合法。

  • JobNotFoundException:JOB不存在。

2. org.activiti.engine.impl

  1. 實現了流程管理服務RepositoryServiceImpl, RuntimeServiceImpl, FormServiceImpl, TaskServiceImpl, HistoryServiceImpl, IdentityServiceImpl, ManagementServiceImpl
  • 實現流程虛擬機PVM

  • 數據持久化,腳本任務,條件表達式EL的解析等等

  • 命令接口的定義

命令接口包.png

2.1 org.activiti.engine.impl.ServiceImpl

  • XXService 的定義

org.activiti.engine.impl.ServiceImpl是流程管理服務的基類,它的派生類包括RepositoryServiceImpl, RuntimeServiceImpl, FormServiceImpl, TaskServiceImpl, HistoryServiceImpl, IdentityServiceImpl, ManagementServiceImpl,它定義了配置管理服務processEngineConfiguration、命令執行接口commandExecutor(activiti方法調用都通過命令模式)。源碼如下所示:


  public class ServiceImpl {

    protected ProcessEngineConfigurationImpl processEngineConfiguration;

    public ServiceImpl() {
    }

    public ServiceImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
      this.processEngineConfiguration = processEngineConfiguration;
    }

    protected CommandExecutor commandExecutor;

    public CommandExecutor getCommandExecutor() {
      return commandExecutor;
    }

    public void setCommandExecutor(CommandExecutor commandExecutor) {
      this.commandExecutor = commandExecutor;
    }
  }

XXServiceImpl繼承類org.activiti.engine.impl.ServiceImpl,并且實現對應的XXService接口。下面是RepositoryServiceImpl示例代碼:


  public class RepositoryServiceImpl extends ServiceImpl implements RepositoryService {
  }

  • XXService的初始化

XXService的初始化在ProcessEngineConfigurationImpl中

   protected RepositoryService repositoryService = new RepositoryServiceImpl();  
   protected RuntimeService runtimeService = new RuntimeServiceImpl();
   protected HistoryService historyService = new HistoryServiceImpl(this);
   protected IdentityService identityService = new IdentityServiceImpl();
   protected TaskService taskService = new TaskServiceImpl(this);
   protected FormService formService = new FormServiceImpl();
   protected ManagementService managementService = new ManagementServiceImpl();

XXServicecommandExecutor初始化在ProcessEngineConfigurationImpl的initService中

 protected void initService(Object service) {
   if (service instanceof ServiceImpl) {
     ((ServiceImpl)service).setCommandExecutor(commandExecutor);
   }
 }

2.2 org.activiti.engine.impl.interceptor

org.activiti.engine.impl.interceptor定義了攔截器和命令。activiti里面所有的指令都是通過命令模式執行,在命令執行之前,可以切入多個攔截器。

攔截器
  • commandContext是命令上下文。

  • command是命令接口,command中定義了execute方法,代碼如下所示:

 public interface Command <T> {
   T execute(CommandContext commandContext);
 }

  • CommandExecutor這個是命令的執行方法,CommandConfigCommandExecutor的配置。CommandExecutor代碼如下所示:

 public interface CommandExecutor {

   /**
    * @return the default {@link CommandConfig}, used if none is provided.
    */
   CommandConfig getDefaultConfig();

   /**
    * Execute a command with the specified {@link CommandConfig}.
    */
   <T> T execute(CommandConfig config, Command<T> command);

   /**
    * Execute a command with the default {@link CommandConfig}.
    */
   <T> T execute(Command<T> command);

 }

  • CommandInterceptor攔截器,在命令執行之前進行攔截,一個命令可以有多個攔截器,這些攔截器通過鏈表鏈接起來順序執行。CommandInterceptor代碼如下:
 public interface CommandInterceptor {

   <T> T execute(CommandConfig config, Command<T> command);

   CommandInterceptor getNext();

   void setNext(CommandInterceptor next);

 }
  • commandExecutor到底是如何注入的?

RuntimeServiceImpl為例, RuntimeServiceImpl繼承類ServiceImpl,ServiceImpl包含CommandExecutor屬性

ProcessEngineConfigurationImpl中有個init方法,里面有對于executor和intecerptor的初始化


 //  初始化各種服務
 protected void initServices() {
     initService(repositoryService);
     initService(runtimeService);
     initService(historyService);
     initService(identityService);
     initService(taskService);
     initService(formService);
     initService(managementService);
 }

 //  初始化服務方法  
 protected void initService(Object service) {
   if (service instanceof ServiceImpl) {
     ((ServiceImpl)service).setCommandExecutor(commandExecutor);
   }
 }

 //  初始化攔截器
 protected void initCommandInterceptors() {
     if (commandInterceptors==null) {
       commandInterceptors = new ArrayList<CommandInterceptor>();
       if (customPreCommandInterceptors!=null) {
         commandInterceptors.addAll(customPreCommandInterceptors);
       }
       commandInterceptors.addAll(getDefaultCommandInterceptors());
       if (customPostCommandInterceptors!=null) {
         commandInterceptors.addAll(customPostCommandInterceptors);
       }
       commandInterceptors.add(commandInvoker);
     }
 }

 //  將攔截器初始化成鏈式結構
 protected void initCommandExecutor() {
   if (commandExecutor==null) {
     CommandInterceptor first = initInterceptorChain(commandInterceptors);
     commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first);
   }
 }

2.3 org.activiti.engine.impl.delegate

org.activiti.engine.impl.delegate實現了監聽器和事件處理,activiti 允許客戶端代碼介入流程的執行,為此提供了這個基礎組件。

activiti5.16 用戶手冊的介紹,監聽器事件處理。

2.3.1 監聽器

監聽器可以捕獲的事件包括:

  1. 流程實例的啟動和結束
  • 選中一條連線
  • 節點的開始和結束
  • 網關的開始和結束
  • 中間事件的開始和結束
  • 開始時間結束或結束事件開始
執行監聽器

DelegateInterceptor是事件攔截器接口,DelegateInvocation是事件調用接口,XXXInvocationDelegateInvocation的實現類,XXXInvocation里面包含監聽接口XXXListener

  • 怎樣添加監聽

下面的流程定義文件包含2個監聽器,event表示時間類型,class表示處理事件的java類。

 <extensionElements>
   <activiti:taskListener event="create" class="com.alfrescoblog.MyTest.imple.CreateTaskDelegate"></activiti:taskListener>
   <activiti:taskListener event="complete" class="com.alfrescoblog.MyTest.imple.MyJavaDelegate"></activiti:taskListener>
 </extensionElements>

CreateTaskDelegate是客戶端實現的監聽類,TaskListener``是activiti的監聽接口。

package com.alfrescoblog.MyTest.imple;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;

public class CreateTaskDelegate implements TaskListener {

  public void notify(DelegateTask delegateTask) {
    // TODO Auto-generated method stub
    System.out.println("創建任務啦?。?); 
  }

}

TaskListener代碼如下所示:


 public interface TaskListener extends Serializable {

   String EVENTNAME_CREATE = "create";
   String EVENTNAME_ASSIGNMENT = "assignment";
   String EVENTNAME_COMPLETE = "complete";
   String EVENTNAME_DELETE = "delete";

   /**
    * Not an actual event, used as a marker-value for {@link TaskListener}s that should be called for all events,
    * including {@link #EVENTNAME_CREATE}, {@link #EVENTNAME_ASSIGNMENT} and {@link #EVENTNAME_COMPLETE} and {@link #EVENTNAME_DELETE}.
    */
   String EVENTNAME_ALL_EVENTS = "all";

   void notify(DelegateTask delegateTask);
 }

  • 監聽怎樣被注入的

BPMN流程文件部署的時候會注入各種listener。比如TaskListener在org.activiti.engine.impl.task.TaskDefinition的addTaskListener方法中被注入,代碼如下:


 public void addTaskListener(String eventName, TaskListener taskListener) {
   if(TaskListener.EVENTNAME_ALL_EVENTS.equals(eventName)) {
     // In order to prevent having to merge the "all" tasklisteners with the ones for a specific eventName,
     // every time "getTaskListener()" is called, we add the listener explicitally to the individual lists
     this.addTaskListener(TaskListener.EVENTNAME_CREATE, taskListener);
     this.addTaskListener(TaskListener.EVENTNAME_ASSIGNMENT, taskListener);
     this.addTaskListener(TaskListener.EVENTNAME_COMPLETE, taskListener);
     this.addTaskListener(TaskListener.EVENTNAME_DELETE, taskListener);

   } else {
     List<TaskListener> taskEventListeners = taskListeners.get(eventName);
     if (taskEventListeners == null) {
       taskEventListeners = new ArrayList<TaskListener>();
       taskListeners.put(eventName, taskEventListeners);
     }
     taskEventListeners.add(taskListener);
   }
 }

  • 監聽在什么時候觸發的

以TaskListener為例,調用鏈:UserTaskActivityBehavior.execute()task.fireEvent(TaskListener.EVENTNAME_CREATE);DelegateInterceptor.handleInvocation()DefaultDelegateInterceptor.handleInvocation()DelegateInvocation.proceed()TaskListenerInvocation.invoke()TaskListener.notify()

UserTaskActivityBehavior 是任務新增、修改、刪除行為,UserTask節點解析(UserTaskParseHandler.executeParse)的時候設置到activiti中,觸發的代碼還沒找到。

 protected void executeParse(BpmnParse bpmnParse, UserTask userTask) {
   ActivityImpl activity = createActivityOnCurrentScope(bpmnParse, userTask, BpmnXMLConstants.ELEMENT_TASK_USER);

   activity.setAsync(userTask.isAsynchronous());
   activity.setExclusive(!userTask.isNotExclusive());

   TaskDefinition taskDefinition = parseTaskDefinition(bpmnParse, userTask, userTask.getId(), (ProcessDefinitionEntity) bpmnParse.getCurrentScope().getProcessDefinition());
   activity.setProperty(PROPERTY_TASK_DEFINITION, taskDefinition);
   activity.setActivityBehavior(bpmnParse.getActivityBehaviorFactory().createUserTaskActivityBehavior(userTask, taskDefinition));
 }

參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容