官术网_书友最值得收藏!

6.3 注冊事件監聽器

下面詳細分析全局事件監聽器和具體類型的事件監聽器是如何注冊使用的。事件監聽器從應用范圍上可以劃分為兩種:一種是全局事件監聽器,負責監聽所有的事件;另一種是具體類型的事件監聽器,只負責部分事件的監聽,例如開發人員可以將所有流程引擎支持的事件按照業務使用場景進行劃分,可以定義一個類只負責監聽所有與任務有關的事件,也可以定義一個類只負責變量事件的監聽等,引擎設計具體類型的事件監聽器的主要意圖是方便開發人員細化、歸類事件,從而使事件監聽器的職責更加清晰和單一,代碼也更加容易維護。

上面提到事件監聽器的注冊和移除工作最終是通過ActivitiEventDispatcherImpl類中持有的ActivitiEventSupport實例對象來完成,下面詳細分析ActivitiEventSupport類是如何進行事件監聽器的注冊工作,整個處理流程如代碼清單6-2所示。

代碼清單6-2 ActivitiEventSupport.java

(1)第1行定義的addEventListener方法用于注冊全局事件監聽器。

addEventListener方法主要用于注冊全局事件監聽器,該方法的處理邏輯非常簡單,首先第2行對listenerToAdd參數進行非空校驗,如果該參數不為空,則第3行判斷eventListeners集合中是否已經存在了listenerToAdd,如果集合中不存在,則第4行將其添加到集合中,該操作主要是為了避免重復注冊事件監聽器。

(2)第7行定義的addEventListener方法用于注冊具體類型的事件監聽器。

首先第8行對listenerToAdd參數進行非空校驗,然后第9行判斷type參數是否為空,如果type參數為空則第10行直接將當前的事件監聽器作為全局事件監聽器進行處理,并通過第1行定義的方法將其注冊到eventListeners集合中;如果type參數不為空,則第12~13行循環遍歷type數組,并調用第17行定義的addTypedEventListener方法注冊具體類型的事件監聽器,該方法的處理邏輯如下。

? 第18行根據type參數從typedListeners集合中獲取該事件下所有的事件監聽器集合listeners。

? 第19行如果listeners集合為空,則首先初始化該集合并將其添加到typedListeners集合中。

? 第23行如果listeners集合中不存在listener元素,則將其添加到listeners集合中。

因為向eventListeners集合中添加元素時,可能存在多個線程同時對集合內容進行操作,所以需要考慮集合數據同步問題,因此上面三個方法中的方法簽名均使用了synchronized關鍵字進行修飾。

ActivitiEventSupport類中的eventListeners集合為List數據結構,初始化該集合時使用了Java中的CopyOnWriteArrayList類,該集合的初始化過程可以參考ActivitiEventSupport類的構造方法。這里需要對CopyOnWriteArrayList類詳細說明:CopyOnWriteArrayList類非常重要,可以使用在高并發場景中,基本思路是這樣的,例如存在一個集合,多個線程都要對集合內容進行操作,當任意一個線程想要改變集合內容時,首先需要把集合中的內容進行一次全復制并形成一個新的容器,這樣任何一個線程想要對原容器中的內容進行修改操作時,只會修改新生成容器中的內容,修改完畢之后將原容器的指針指向新容器,從而達到修改集合內容的目的,這是一種典型的懶惰延時策略,這樣做的好處就是每次修改容器內容時操作的永遠是新容器,從而可以對CopyOnWriteArrayList進行并發讀而不需要加同步鎖,由于當前容器集合永遠不會添加新元素,讀寫操作永遠在不同的容器中進行,是典型的讀寫分離思想。

CopyOnWriteArrayList類的缺點:在寫操作過程中內存會同時存在兩個容器,這樣程序就會占用大量的內存,并且寫操作過程客戶端可能需要從原容器中讀取最新的數據,而原容器的指針在指向新容器之前程序讀取的永遠是原容器的值,這樣可能會造成數據短時間內不一致,如果開發人員期望寫數據立刻就能被讀取到,必須要求保證數據的實時性、一致性,那么很顯然使用CopyOnWriteArrayList容器不是一種明智的選擇。

注意

Java中的Map為引用類型,如果獲取到某個Map的引用,則程序操作引用對象的時,本質上就是對Map進行操作。

主站蜘蛛池模板: 临清市| 平南县| 宝鸡市| 界首市| 民县| 邹平县| 驻马店市| 梁河县| 达拉特旗| 铜陵市| 唐河县| 祁门县| 盘锦市| 长春市| 宜兰市| 赤城县| 汽车| 廉江市| 漳平市| 乐亭县| 陇川县| 石狮市| 阿坝| 新田县| 通州区| 宝丰县| 股票| 武冈市| 图木舒克市| 汾阳市| 榆林市| 拜泉县| 阿拉尔市| 赤壁市| 灵山县| 札达县| 宽甸| 紫金县| 南华县| 澎湖县| 酉阳|