1. 程式人生 > 其它 >activiti學習筆記(六) 監聽器

activiti學習筆記(六) 監聽器

activiti全域性監聽器

全域性監聽器主要使用的場景就是監控這個流程的啟動和結束。流程開始的時候可以監控,流程結束的時候也可以監控

監聽器的介面

public interface ActivitiEventListener {

  /**當時間被執行時呼叫該方法*/
  void onEvent(ActivitiEvent event);

 /**
  * @author 鄭小康
  * 這個是onEvent執行失敗之後進行的處理
  *
  * 如果是true則返回onEvent執行失敗的異常
  *
  * 如果是false則忽略這個異常
  * */
  boolean isFailOnException();
}

初始化所有監聽器

將所有全域性監聽器和型別監聽器給加入到當前eventListeners裡面,這裡只是初始化過程

/**
   * @author 鄭小康
   *
   * 事件監聽器分為兩種
   *
   * 1.如果eventDispatcher為空,則例項化ActivitiEventDispatcherImpl
   *
   * 2.設定eventDispatcher的狀態為enableEventDispatcher,其值為true 預設支援事件轉發
   *
   * 3.遍歷當前流程例項所有的eventListeners監聽器,將其新增到eventDispatcher
   *
   * 4.遍歷所有typedEventListeners 以entry為key進行新增
   *   在cfg.xml檔案定義:
   *    <property name="typedEventListeners">
   *      <map>
   *           <entry key="JOB_EXECUTION_SUCCESS,JOB_EXECUTION_FAILURE" >
   *               <list>
   *                  <bean class="org.activiti.engine.example.MyJobEventListener" />
   *                </list>
   *           </entry>
   *     </map>
   *   </property>
   * */
  public void initEventDispatcher() {
    if (this.eventDispatcher == null) {
      this.eventDispatcher = new ActivitiEventDispatcherImpl();
    }

    this.eventDispatcher.setEnabled(enableEventDispatcher);

    if (eventListeners != null) {
      for (ActivitiEventListener listenerToAdd : eventListeners) {
        this.eventDispatcher.addEventListener(listenerToAdd);
      }
    }

    if (typedEventListeners != null) {
      for (Entry<String, List<ActivitiEventListener>> listenersToAdd : typedEventListeners.entrySet()) {
        // Extract types from the given string
        ActivitiEventType[] types = ActivitiEventType.getTypesFromString(listenersToAdd.getKey());

        for (ActivitiEventListener listenerToAdd : listenersToAdd.getValue()) {
          this.eventDispatcher.addEventListener(listenerToAdd, types);
        }
      }
    }

  }

初始化監聽器配置過程

   其實在流程例項中注入相對應的屬性bean

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://127.0.0.1:3306/activiti?useUnicode=true&characterEncoding=UTF-8
			</value>
		</property>
		<property name="username">
			<value>root</value>
		</property>
		<property name="password" value="fadp" />
	</bean>

	<bean id="processEngine1" name="processEngineConfiguration"
		class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
		<property name="dataSource" ref="dataSource" />
		<property name="databaseSchemaUpdate" value="true" />
		<property name="eventListeners">
			<list>
				<bean class="com.event.MyEventListener" />
			</list>
		</property>
	</bean>

</beans>

監聽器在流程例項啟動時候的應用

       在構建流程例項的時候,會構建一個流程例項,在器最後會構建一個引擎啟動時間,呼叫所有監聽器的onEvent 方法

public ProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) {
     .......
    //呼叫時間轉發器,構建一個事件例項ActivitiEvent型別為ENGINE_CREATED,然後進行事件轉發
    processEngineConfiguration.getEventDispatcher().dispatchEvent(ActivitiEventBuilder.createGlobalEvent(ActivitiEventType.ENGINE_CREATED));
  }
/**
   * 1.enabled判斷,預設為true進行事件轉發
   *
   * 2.FIXME:尚未理解
   * */
  @Override
  public void dispatchEvent(ActivitiEvent event) {
    if (enabled) {
      eventSupport.dispatchEvent(event);
    }

    if (event.getType() == ActivitiEventType.ENTITY_DELETED && event instanceof ActivitiEntityEvent) {
      ActivitiEntityEvent entityEvent = (ActivitiEntityEvent) event;
      if (entityEvent.getEntity() instanceof ProcessDefinition) {
        // process definition deleted event doesn't need to be dispatched to event listeners
        return;
      }
    }
    

    CommandContext commandContext = Context.getCommandContext();
    if (commandContext != null) {
      BpmnModel bpmnModel = extractBpmnModelFromEvent(event);
      if (bpmnModel != null) {
        ((ActivitiEventSupport) bpmnModel.getEventSupport()).dispatchEvent(event);
      }
    }
    
  }
 /**
   * @author  鄭小康
   *
   * 1.對當前轉化的事件做非空校驗
   *
   * 2.轉化所有全域性事件監聽器
   *
   * 3.獲取跟當前事件型別相同的事件監聽器,並進行事件轉化進行執行
   *
   * */
  public void dispatchEvent(ActivitiEvent event) {
    if (event == null) {
      throw new ActivitiIllegalArgumentException("Event cannot be null.");
    }

    if (event.getType() == null) {
      throw new ActivitiIllegalArgumentException("Event type cannot be null.");
    }

    //執行所有全域性事件監聽器
    if (!eventListeners.isEmpty()) {
      for (ActivitiEventListener listener : eventListeners) {
        dispatchEvent(event, listener);
      }
    }

    //獲取跟當前事件型別相同的事件監聽器,並進行事件轉化進行執行
    List<ActivitiEventListener> typed = typedListeners.get(event.getType());
    if (typed != null && !typed.isEmpty()) {
      for (ActivitiEventListener listener : typed) {
        dispatchEvent(event, listener);
      }
    }
  }

測試

        @Test
	public void getDefaultProcessEngine() {
		ProcessEngineConfiguration pec = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("com/event/activiti.cfg.xml");
		ProcessEngine pe1 = pec.buildProcessEngine();
	}

測試結果

Event received: ENGINE_CREATED

       其中還有一種動態載入監聽器的過程,通過第一個流程例項獲取監聽器的集合,進行新增,在第二個流程例項中就可以這樣用了,為什麼是這樣呢,因為spring獲取bean是單例模式,監聽器引用型別指向的是同一個變數,使用過程如下:

        @Before
	public void init() {
		processEngine = ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource(
						"com/activiti_study/ch24/activiti1.cfg.xml")
				.buildProcessEngine();
		repositoryService = processEngine.getRepositoryService();
		activitiEventDispatcher = ((ProcessEngineConfigurationImpl) processEngine
				.getProcessEngineConfiguration()).getEventDispatcher();
	}
        @Test
	public void testAddEventListener() {
		ShareniuTaskEventListener2 shareniuTaskEventListener2 = new ShareniuTaskEventListener2();
		activitiEventDispatcher.addEventListener(shareniuTaskEventListener2);
		ProcessEngine pe = ProcessEngines.getDefaultProcessEngine();
		System.out.println(pe);

		processEngine = ProcessEngineConfiguration
				.createProcessEngineConfigurationFromResource(
						"com/activiti_study/ch24/activiti1.cfg.xml")
				.buildProcessEngine();
	}