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 代碼示例  

import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; /** * * @author zq * */ public class HelloWorld implements ApplicationEventPublisherAware{ private String word; private ApplicationEventPublisher tradeEventPublisher; public void setWord(String w){ this.word = w; } public void say(){ System.out.println("say : "+ this.word); //construct a TradeEvent instance and publish it TradeEvent tradeEvent = new TradeEvent(new String("tradeEvent")); this.tradeEventPublisher.publishEvent(tradeEvent); } @Override public void setApplicationEventPublisher( ApplicationEventPublisher applicationEventPublisher) { // TODO Auto-generated method stub this.tradeEventPublisher = applicationEventPublisher; } }

2.接受事件
  2.1需要實現的接口org.springframework.context.ApplicationListener
  2.2代碼示例

import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextStartedEvent; public class TradeContextListener implements ApplicationListener{ @Override public void onApplicationEvent(ApplicationEvent e) { System.out.println(e.getClass().toString()); // TODO Auto-generated method stub if (e instanceof ContextStartedEvent){ System.out.println("it was contextStartedEvent"); } if (e instanceof TradeEvent){ System.out.println(e.getSource()); } } }

3配置文件

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="helloWorld" class="study.HelloWorld"> <property name="word" value="hello world"/> </bean> <bean id="tradeContextListener" class="study.TradeContextListener"/> </beans>

4.測試代碼

import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import study.HelloWorld; public class TestHelloWorld { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext applicationContext = new ClassPathXmlApplicationContext("study-context.xml"); HelloWorld bean = (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()方法中添加事件處理代碼,如下:

1 package ioc.test;
2
3 //Import省略
4 publicclass ApplicationEventListenerimplements ApplicationListener {
5
6 publicvoid onApplicationEvent(ApplicationEvent event) {
7
8 //如果是容器刷新事件
9 if(eventinstanceof ContextClosedEvent ){
10             System.out.println(event.getClass().getSimpleName()+" 事件已發生!");   
11         }elseif(eventinstanceof ContextRefreshedEvent ){//如果是容器關閉事件
12             System.out.println(event.getClass().getSimpleName()+" 事件已發生!");   
13         }elseif(eventinstanceof ContextStartedEvent ){
14             System.out.println(event.getClass().getSimpleName()+" 事件已發生!");
15         }elseif(eventinstanceof ContextStoppedEvent){
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內定事件,代碼如下:

1 package ioc.test;
2
3 //import省略
4 publicclass TesMain {
5
6 publicstaticvoid main(String[] args) {
7         AbstractApplicationContext ac=new ClassPathXmlApplicationContext("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容器會自動將其注冊。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM