activiti學習筆記(六) 監聽器
阿新 • • 發佈:2022-05-03
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();
}