1. 程式人生 > 實用技巧 >spring釋出和接收定製的事件(spring事件傳播)

spring釋出和接收定製的事件(spring事件傳播)

有事件,即有事件監聽器. 有人問你spring監聽器有哪些你看了下文即也知道了。

事件傳播

ApplicationContext基於Observer模式(java.util包中有對應實現),提供了針對Bean的事件傳

播功能。通過Application. publishEvent方法,我們可以將事件通知系統內所有的

ApplicationListener。

事件傳播的一個典型應用是,當Bean中的操作發生異常(如資料庫連線失敗),則通過事件傳播

機制通知異常監聽器進行處理。在筆者的一個專案中,就曾經藉助事件機制,較好的實現了當系統

異常時在監視終端上報警,同時傳送報警SMS至管理員手機的功能。

ApplicationContext容器提供了容器內部事件釋出功能,是繼承自JavaSE標準自定義事件類而實現的。

JavaSE標準自定義事件結構不在此詳細描述,一張圖很直觀的描述清楚:

EventObject,為JavaSE提供的事件型別基類,任何自定義的事件都繼承自該類,例如上圖中右側灰色的各個事件。spring中提供了該介面的子類ApplicationEvent。

EventListener為JavaSE提供的事件監聽者介面,任何自定義的事件監聽者都實現了該介面,如上圖左側的各個事件監聽者。Spring中提供了該介面的子類ApplicationListener介面。

JavaSE中未提供事件釋出者這一角色類,由各個應用程式自行實現事件釋出者這一角色。Spring中提供了ApplicationEventPublisher介面作為事件釋出者,並且ApplicationContext實現了這個介面,擔當起了事件釋出者這一角色。但ApplicationContext在具體實現上有所差異,Spring提供了ApplicationEventMulticaster介面,負責管理ApplicationListener和釋出ApplicationEvent。ApplicationContext會把相應的事件相關工作委派給ApplicationEventMulticaster介面實現類來做。類圖如下所示:


事件釋出時序圖如下:


-------------------------------------------------------------------------------------------------

Spring中提供一些Aware相關的介面,BeanFactoryAware、 ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,其中最常用到的是ApplicationContextAware。實現ApplicationContextAware的Bean,在Bean被初始後,將會被注入ApplicationContext的例項。ApplicationContextAware提供了publishEvent()方法,實現Observer(觀察者)設計模式的事件傳播機,提供了針對Bean的事件傳播功能。通過Application.publishEvent方法,我們可以將事件通知系統內所有的ApplicationListener。

Spring事件處理一般過程:

◆定義Event類,繼承org.springframework.context.ApplicationEvent。
◆編寫釋出事件類Publisher,實現org.springframework.context.ApplicationContextAware介面。
◆覆蓋方法setApplicationContext(ApplicationContext applicationContext)和釋出方法publish(Object obj)。
◆定義時間監聽類EventListener,實現ApplicationListener介面,實現方法onApplicationEvent(ApplicationEvent event)。

1.釋出

1.1事件的釋出者需要實現的介面

org.springframework.context.ApplicationEventPublisherAware

1.2 程式碼示例

importorg.springframework.context.ApplicationEventPublisher;importorg.springframework.context.ApplicationEventPublisherAware;/****@authorzq**/publicclassHelloWorldimplementsApplicationEventPublisherAware{privateStringword;privateApplicationEventPublishertradeEventPublisher;publicvoidsetWord(Stringw){this.word=w;}publicvoidsay(){System.out.println("say:"+this.word);//constructaTradeEventinstanceandpublishitTradeEventtradeEvent=newTradeEvent(newString("tradeEvent"));this.tradeEventPublisher.publishEvent(tradeEvent);}@OverridepublicvoidsetApplicationEventPublisher(ApplicationEventPublisherapplicationEventPublisher){//TODOAuto-generatedmethodstubthis.tradeEventPublisher=applicationEventPublisher;}}

2.接受事件

2.1需要實現的介面org.springframework.context.ApplicationListener

2.2程式碼示例

importorg.springframework.context.ApplicationEvent;importorg.springframework.context.ApplicationListener;importorg.springframework.context.event.ContextStartedEvent;publicclassTradeContextListenerimplementsApplicationListener{@OverridepublicvoidonApplicationEvent(ApplicationEvente){System.out.println(e.getClass().toString());//TODOAuto-generatedmethodstubif(einstanceofContextStartedEvent){System.out.println("itwascontextStartedEvent");}if(einstanceofTradeEvent){System.out.println(e.getSource());}}}

3配置檔案

<?xmlversion="1.0"encoding="utf-8"?><!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"><beans><beanname="helloWorld"class="study.HelloWorld"><propertyname="word"value="helloworld"/></bean><beanid="tradeContextListener"class="study.TradeContextListener"/></beans>

4.測試程式碼

importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;importstudy.HelloWorld;publicclassTestHelloWorld{/***@paramargs*/publicstaticvoidmain(String[]args){//TODOAuto-generatedmethodstubApplicationContextapplicationContext=newClassPathXmlApplicationContext("study-context.xml");HelloWorldbean=(HelloWorld)applicationContext.getBean("helloWorld");bean.say();}}

Spring中ApplicationContext的事件機制--- 內定事件)

Spring中已經定義了五個標準事件,分別介紹如下:

1) ContextRefreshedEvent:當ApplicationContext初始化或者重新整理時觸發該事件。

2) ContextClosedEvent:當ApplicationContext被關閉時觸發該事件。容器被關閉時,其管理的所有單例Bean都被銷燬。

3) RequestHandleEvent:在Web應用中,當一個http請求(request)結束觸發該事件。

ContestStartedEvent:Spring2.5新增的事件,當容器呼叫ConfigurableApplicationContext的Start()方法開始/重新開始容器時觸發該事件。

5) ContestStopedEvent:Spring2.5新增的事件,當容器呼叫ConfigurableApplicationContext的Stop()方法停止容器時觸發該事件。

下面通過一個例子展示如何處理Spring內定的事件(例程3.8)。建立一個Java工程,新增Spring開發能力後,新建ioc.test包。在包中新建ApplicationEventListener類,實現ApplicationListener介面,在onApplicationEvent()方法中新增事件處理程式碼,如下:

1packageioc.test;
2
3//Import省略
4publicclassApplicationEventListenerimplementsApplicationListener {
5
6publicvoidonApplicationEvent(ApplicationEvent event) {
7
8//如果是容器重新整理事件
9if(eventinstanceofContextClosedEvent ){
10 System.out.println(event.getClass().getSimpleName()+"事件已發生!");
11 }elseif(eventinstanceofContextRefreshedEvent ){//如果是容器關閉事件
12 System.out.println(event.getClass().getSimpleName()+"事件已發生!");
13 }elseif(eventinstanceofContextStartedEvent ){
14 System.out.println(event.getClass().getSimpleName()+"事件已發生!");
15 }elseif(eventinstanceofContextStoppedEvent){
16 System.out.println(event.getClass().getSimpleName()+"事件已發生!");
17 }else{
18 System.out.println("有其它事件發生:"+event.getClass().getName());
19 }
20
21 }
22
23}
24



在Spring配置檔案中定義一個Bean,類為ApplicationEventListener,程式碼如下:

1<?xml version="1.0" encoding="UTF-8"?>
2<beans…………
3
4 <bean id="ApplicationEventListener"class="ioc.test.ApplicationEventListener"/>
5
6</beans>
7



新增含有主方法的TesMain類,在主方法中,呼叫容器的相應方法,觸發Spring內定事件,程式碼如下:

1packageioc.test;
2
3//import省略
4publicclassTesMain {
5
6publicstaticvoidmain(String[] args) {
7 AbstractApplicationContext ac=newClassPathXmlApplicationContext("applicationContext.xml");
8
9
10// ac.refresh();//觸發ContextRefreshedEvent事件
11 ac.start();//觸發ContextStartedEvent事件
12 ac.stop();//觸發ContextStoppedEvent事件
13 ac.close();//關閉容器,觸發ContextClosedEvent事件
14
15 }
16}
17




執行主類,控制檯輸出如下:






從例子中可以知道,要註冊事件監聽器,我們只需要把它配置成一個Bean即可,ApplicationContext容器會自動將其註冊。


轉載於:https://blog.51cto.com/wenwenheyaoyao/1867312