Symfony2 EventDispatcher組件

一個插件系統中,A插件在不影響其它插件的前提下,添加新的方法,或者在一個方法運行前做一些準備工作,通過繼承來實現擴展是很不容易的,由于插件之間的關聯關系,A插件的改變也會使得關聯的插件被動的修改。
Symfony2的EventDispatcher組件實現了中介者(mediator)模式,實現了插件之間的解耦和關聯的關系。
舉個栗子,在HttpKernel組件中,一旦Response被創建了,在Response發送給客戶端的時候,允許系統的其它模塊修改它是很有必要和很有用的(例如:在頭部添加緩存字段)。Symfony2內核調度kernel.response事件,那么監聽該事件的監聽器就可以修改Response對象了:
a) 監聽器(PHP對象)告訴一個特定的dispatcher類,它要監聽kernel.response事件;
b) 在某一時刻,Symfony就會告訴dispatcher調度kernel.response事件,把一個包含Response對象的Event對象傳入事件調度方法EventDispatcher::dispatch()
c) dispatcher通知所有監聽kernel.response事件的監聽器運行,允許這些監聽器修改Response對象。
使用方法
Events
當一個事件被調度,該事件會有一個唯一的名稱(例如:kernel.response),可以被任意多個監聽器監聽。同時實例化一個Event對象,并傳入到所有的監聽器中。在后面會看到,Event對象包含了被調度事件的數據。
命名規范
事件名可以是任意的字符串,但是可以遵循以下幾點命名規范:
* 只使用小寫字符、數字、點、下劃線;
* 前綴名使用帶有點的命名;
* 結束部分的名字使用一個能表達當前事件行為的動詞;
事件名和事件對象
dispatcher調度事件通知監聽器時候,會把一個Event對象作為參數傳入到監聽器中。基類的Event非常簡單,只有一個停止事件傳遞給下一個監聽器的方法,沒有太多別的了。
通常,一個特定事件的數據都會保存到Event對象中,方便把數據傳遞給監聽器。在kernel.response事件中,傳入到監聽器的Event對象是子類FliterResponseEvent的對象,FliterResponseEvent是Event的子類。FliterResponseEvent包含getReponse和setResponse方法,允許監聽器獲得或者修改Response對象。
總的來說:創建一個監聽特定事件的監聽器的時候,Event的一個子類會傳入到監聽器中,監聽器可以通過該子類的方法獲得和修改信息。
事件調度器(dispatcher)
dispatcher是事件調度系統的核心,一般來說,一個dispatcher內包含一個監聽器的列表,當一個事件需要被調度的時候,dispatcher就會通知它包含的所有監聽該事件的監聽器。
1 use Symfony\Component\EventDispatcher\EventDispatcher;
2 
3 $dispatcher = new EventDispatcher();
關聯監聽器
把監聽器添加到dispatcher上,監聽特定的事件,那么該事件被調度的時候,dispatcher就會通知監聽器工作了。dispatcher使用addListener方法把一個監聽器(PHP callable)添加到一個事件上。
1 $listener = new AcmeListener();
2 $dispatcher->addListener('foo.action', array($listener, 'onFooAction'));
addListener方法有三個參數:
* 監聽器需要監聽是的事件的名稱;
* 監聽器(一個PHP callable);
* 一個可選的表示優先級的整數(數值越高優先級越高,監聽器就會更早的被觸發),默認為0,如果優先級一樣,那么誰先添加就先觸發;
PHP callable是指能作為參數傳入call_user_func()或者傳入is_callable()函數執行后返回true的PHP 變量。PHP callable可以是 \Closure實例,一個實現了__invoke方法的對象,或者是表示一個函數的字符串,或者一個表示對象方法或者類方法的數組。
到目前為止,我們看過把一個PHP對象作為監聽器,我們也可以把Closure對象作為監聽器。
1 use Symfony\Component\EventDispatcher\Event;
2 
3 $dispatcher->addListener('foo.action', function (Event $event) {
4     // will be executed when the foo.action event is dispatched
5 });
在上面的例子中,foo.action事件被調度,dispatcher就調用AcmeListener::onFooAction方法,并把Event對象作為唯一的參數傳入方法中。
 1 use Symfony\Component\EventDispatcher\Event;
 2 
 3 class AcmeListener
 4 {
 5     // ...
 6 
 7     public function onFooAction(Event $event)
 8     {
 9         // ... do something
10     }
11 }

    ?在實際使用中,都是傳入一個特定的Event子類的對象到監聽器,例如FilterResponseEvent:

1 use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
2 
3 public function onKernelResponse(FilterResponseEvent $event)
4 {
5     $response = $event->getResponse();
6     $request = $event->getRequest();
7 
8     // ...
9 }
創建和調度事件
除了系統內置的事件,我們也可以創建和調度自定義的事件。這是很有好處的,當我們使用第三方類庫的時,還有可以使不同的組件之間解耦,使系統更靈活健壯。
靜態的Events類
假如我們要創建一個事件——store.order——當訂單被創建的時候就會被觸發。
namespace Acme\StoreBundle;final class StoreEvents
{/*** The store.order event is thrown each time an order is created* in the system.** The event listener receives an* Acme\StoreBundle\Event\FilterOrderEvent instance.** @var string*/const STORE_ORDER = 'store.order';
}
這個類并沒有什么方法,也不做什么操作,只是定義了事件名稱,方便管理和組織事件。監聽這個事件的監聽器都會被傳入一個FilterOrderEvent對象。
創建一個Event對象
接著,當你調度這個新的事件的時候,會創建一個Event對象傳如到dispatcher的dispatch()方法,dispatcher就把這個Event對象傳給所有的監聽該事件的監聽器。如果我們不需要向監聽器傳入任何信息,那么可以使用系統默認的Symfony\Component\EventDispatcher\Event?類。然而,很多時候,我們都需要傳入特定的信息到監聽器,那么我們可以創建一個類繼承Symfony\Component\EventDispatcher\Event。
例如,我們需要在所有的監聽器中傳入order對象:
 1 namespace Acme\StoreBundle\Event;
 2 
 3 use Symfony\Component\EventDispatcher\Event;
 4 use Acme\StoreBundle\Order;
 5 
 6 class FilterOrderEvent extends Event
 7 {
 8     protected $order;
 9 
10     public function __construct(Order $order)
11     {
12         $this->order = $order;
13     }
14 
15     public function getOrder()
16     {
17         return $this->order;
18     }
19 }
所有監聽器都可以通過FilterOrderEvent的getOrder方法獲得order對象。
調度事件
dispatcher的dispatch()方法通知監聽給定的事件的所有監聽器,有兩個參數,一個是需要調度的事件名,另一個就是傳給所有監聽器的Event對象。
 1 use Acme\StoreBundle\StoreEvents;
 2 use Acme\StoreBundle\Order;
 3 use Acme\StoreBundle\Event\FilterOrderEvent;
 4 
 5 // the order is somehow created or retrieved
 6 $order = new Order();
 7 // ...
 8 
 9 // create the FilterOrderEvent and dispatch it
10 $event = new FilterOrderEvent($order);
11 $dispatcher->dispatch(StoreEvents::STORE_ORDER, $event);

    FilterOrderEvent對象作為參數傳入到dispatch方法,現在,任何監聽store.order事件的監聽器都會接收到FilterOrderEvent對象,并通過調用getOrder方法獲得order對象。

1 // some listener class that's been registered for "store.order" event
2 use Acme\StoreBundle\Event\FilterOrderEvent;
3 
4 public function onStoreOrder(FilterOrderEvent $event)
5 {
6     $order = $event->getOrder();
7     // do something to or with the order
8 }
Event Subscribers??
最普遍的監聽事件的方法是注冊一個監聽器到dispatcher中,一個監聽器可以監聽一個或者多個事件。
還有另一種監聽事件的方法是使用Event SubScriber,Event SubScriber是一個PHP類,能夠準確的告訴dispatcher它訂閱了那些事件。實現EventSubscriberInterface接口,該接口有一個靜態的方法getSubscriberdEvents。
namespace Acme\StoreBundle\Event;use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;class StoreSubscriber implements EventSubscriberInterface
{public static function getSubscribedEvents(){return array('kernel.response' => array(array('onKernelResponsePre', 10),array('onKernelResponseMid', 5),array('onKernelResponsePost', 0),),'store.order'     => array('onStoreOrder', 0),);}public function onKernelResponsePre(FilterResponseEvent $event){// ...
    }public function onKernelResponseMid(FilterResponseEvent $event){// ...
    }public function onKernelResponsePost(FilterResponseEvent $event){// ...
    }public function onStoreOrder(FilterOrderEvent $event){// ...
    }
}

這個監聽器類很簡單,告訴了dispatcher監聽了什么事件,還有監聽的事件觸發的方法。addSubscriber()方法把subscriber注冊到dispatcher。

1 use Acme\StoreBundle\Event\StoreSubscriber;
2 
3 $subscriber = new StoreSubscriber();
4 $dispatcher->addSubscriber($subscriber);
dispatcher準確的把Subscriber注冊到EventSubscriberInterface::getSubscriberdEvents()返回的事件里,EventSubscriberInterface::getSubscriberdEvents()方法返回一個數組,數組的鍵對應Subscriber監聽的事件,值對應這Subscriber處理該事件調用的一個方法或者一組方法。上面的例子中,一組監聽器的方法對應這一個事件,同時我們也可以設置優先級來控制這組方法的執行先后順序。當kernel.response事件被觸onKernelResponsePre,?onKernelResponseMid, 和?onKernelResponsePost三個方法就會先后執行。
停止事件的傳遞
在一些情況下,監聽器可以停止事件傳遞下去,防止后續的監聽器被調用,換句話說,監聽器必須通知dispatcher停止傳遞事件給后續的監聽器。在監聽器里面實現stopPropagation()方法:
1 use Acme\StoreBundle\Event\FilterOrderEvent;
2 
3 public function onStoreOrder(FilterOrderEvent $event)
4 {
5     // ...
6 
7     $event->stopPropagation();
8 }
那么,監聽了store.order事件的還沒有執行的監聽器就不會在被執行。
通過isPropagationStopped()方法可以判斷一個事件是否被停止。
1 $dispatcher->dispatch('foo.event', $event);
2 if ($event->isPropagationStopped()) {
3     // ...
4 }

?

轉載于:https://www.cnblogs.com/szuyuan/p/4015843.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/375573.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/375573.shtml
英文地址,請注明出處:http://en.pswp.cn/news/375573.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【轉】漫談ANN(2):BP神經網絡

上一次我們講了M-P模型,它實際上就是對單個神經元的一種建模,還不足以模擬人腦神經系統的功能。由這些人工神經元構建出來的網絡,才能夠具有學習、聯想、記憶和模式識別的能力。BP網絡就是一種簡單的人工神經網絡。我們的第二話就從BP神經網絡…

給定一個值S,在有序數組中找出兩個元素A和B,使 A+B = S.

在網上看到過一個面試題,感覺挺有意思,看別人的代碼寫的邏輯不夠謹慎,重寫了一個,較真了又。。。 package com.array7.algorithm;public class AlgorithmTest {public static void main(String[] args) {int[] arr {2 ,4 ,5 ,8 ,…

二叉樹的最小深度

給定一個二叉樹,找出其最小深度。 最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。 說明: 葉子節點是指沒有子節點的節點。 示例: 給定二叉樹[3,9,20,null,null,15,7] 3/ \9 20/ \15 7返回它的最小深度 2. c 廣度優先 /*** Definition for a b…

(轉)會議期刊論文發表介紹(計算機科學領域)

轉自:http://blog.csdn.net/babyfacer/archive/2009/07/25/4377552.aspx 一、計算機科學期刊介紹計算機科學的publication最大特點在于:極度重視會議,而期刊則通常只用來做re- publication。大部分期刊文章都是會議論文的擴展版,首…

笑男手札:SharePoint 2013 單一服務器場環境恢復數據庫內容

SharePoint 2013 單一服務器場環境恢復數據庫內容 笑男的公司服務很多客戶,當然,這些客戶都很挑剔,所以一般情況下生產(Prod)環境的服務是不能停的。 當然,如果你將包含相同網站集的數據庫連接到同一個服務…

數組中數字出現的次數

一個整型數組 nums 里除兩個數字之外,其他數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。要求時間復雜度是O(n),空間復雜度是O(1)。 示例 1: 輸入:nums [4,1,4,6] 輸出:[1,6] 或 [6,1]示例 2:…

【轉】String Date Calendar之間的轉換

1.Calendar 轉化 String Calendar calendat Calendar.getInstance(); SimpleDateFormat sdf new SimpleDateFormat("yyyy-MM-dd"); String dateStr sdf.format(calendar.getTime()); 2.String 轉化Calendar String str"2012-5-27"; SimpleDateFormat sd…

圖解 深入淺出 JavaWeb:Servlet 再說幾句

Writer :BYSocket(泥沙磚瓦漿木匠) 微 博:BYSocket 豆 瓣:BYSocket FaceBook:BYSocket Twitter :BYSocket 上一篇的《 Servlet必會必知 》受到大家一致好評 — (感謝 讀…

react.js 從零開始(五)React 中事件的用法

事件系統 虛擬事件對象 事件處理器將會傳入虛擬事件對象的實例,一個對瀏覽器本地事件的跨瀏覽器封裝。它有和瀏覽器本地事件相同的屬性和方法,包括 stopPropagation() 和 preventDefault(),但是沒有瀏覽器兼容問題。 如果因為一些因素&#x…

乘積的最大子數組

給你一個整數數組 nums ,請你找出數組中乘積最大的連續子數組(該子數組中至少包含一個數字),并返回該子數組所對應的乘積。 示例 1: 輸入: [2,3,-2,4] 輸出: 6 解釋: 子數組 [2,3] 有最大乘積 6。示例 2: 輸入: [-2,0,-1] 輸出…

javascript new

1. 僅function可以使用new 2. function使用new時,會拷貝function中this的內容給新對象,并將function的prototype指向新對象(如果該function沒有prototype,則指向Object的prototype) 注:function本身不是Obj…

!+\v1 用來“判斷瀏覽器類型”還是用來“IE判斷版本”的問題!

這種寫法是利用各瀏覽器對轉義字符"\v"的理解不同來判斷瀏覽器類型。在IE中,"\v"沒有轉義,得到的結果為"v"。而在其他瀏覽器中"\v"表示一個垂直制表符,所以ie解析的"\v1" 為 "v1&quo…

三個數的最大乘積

給定一個整型數組,在數組中找出由三個數組成的最大乘積,并輸出這個乘積。 示例 1: 輸入: [1,2,3] 輸出: 6示例 2: 輸入: [1,2,3,4] 輸出: 24注意: 給定的整型數組長度范圍是[3,104],數組中所有的元素范圍是[-1000, 1000]。 輸入的數組中任…

VB.NET 數組的定義 動態使用 多維數組

我們都知道在全部程序設計語言中數組都是一個非常重要的概念,數組的作用是同意程序猿用同一個名稱來引用多個變量,因此採用數組索引來區分這些變量。非常多情況下利用數組索引來設置一個循環,這樣就能夠高效地處理復雜的情況,因此…

web.xml 中的listener、 filter、servlet 加載順序

1:首先是context-param節點 2:接著配置和調用listeners 并開始監聽 3:然后配置和調用filters filters開始起作用 4:最后加載和初始化配置在load on startup的servlets轉載于:https://www.cnblogs.com/dwchenxj/p/4787717.html

這么多個月,我頭一次體驗用類的概念來寫驅動

原來感覺一樣是那么爽阿。。。快樂得不得了。。。轉載于:https://www.cnblogs.com/suanguade/p/4038190.html

設置Chrome忽略網站證書錯誤

本人在XP下使用Chrome。總是莫名其妙的提示整數錯誤,一部分https網站無法直接訪問。網上找了下,把解決思路記錄下來。 解決這個問題很簡單,只需要修改你平時用來啟動Chrome的快捷方式就可以忽略掉證書錯誤. 具體的操作方法是這樣的: 找到你的Chrome快捷方…

Android開發之合并文件的幾種方式

以下介紹合并文件的幾種方式,并通過合并amr文件來舉例介紹合并文件的詳細流程。amr格式的文件頭是6字節,所以在進行文件合并的時候要減去除第一個文件以外的其它文件的文件頭。 注意:不同文件的文件頭是不一樣的,所以在合并的時候…

數組中出現次數超過一半的數

數組中有一個數字出現的次數超過數組長度的一半&#xff0c;請找出這個數字。 你可以假設數組是非空的&#xff0c;并且給定的數組總是存在多數元素。 示例 1: 輸入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 輸出: 2限制&#xff1a; 1 < 數組長度 < 50000class Solution { pub…

中國寒龍反網絡病毒聯盟核心小組:官方公告,近期本站將會發布各種編程技術視頻教程,詳情請點擊我們的以下公告!...

大家好&#xff0c;我是中國寒反網絡病毒聯盟官方客服&#xff01; 近期&#xff0c;本站將全面升級&#xff0c;本站發布各種編程視頻教程&#xff0c;包括C,c#以及VB&#xff0c;VB.net&#xff0c;E&#xff0c;等相關編程語言入門視頻教程&#xff0c;每天會定期更新視頻教…