Spring ApplicationContext的事件機制


  ApplicationContext的事件機制是觀察者設計模式的實現,通過 ApplicationEvent 類和 ApplicationListener 接口,可以實現 ApplicationContext 的事件處理。如果容器中有一個 ApplicationListener Bean 每當 ApplicationContext 發布 ApplicationEvent時,ApplicationListener Bean將自動觸發。

  Spring的事件框架有如下兩個重要成員。

  》ApplicationEvent: 容器事件,必須由 ApplicationContext發布。

  》ApplicationListener: 監聽器,可有容器中的任何監聽器Bean擔任

  實際上,Spring 的事件機制與所有的事件機制都基本類似,他們都需要 事件源事件事件監聽器 組成。只是此處的事件源是ApplicationContext。

  下圖簡單示范了ApplicationContext事件

  

 

  下面的程序僵屍翻生Spring容器的事件程序 。程序先定義了一個ApplicationContext類,其對象就是一個Spring容器事件。代碼如下:

 1 import org.springframework.context.ApplicationEvent;
 2 
 3 public class EmailEvent extends ApplicationEvent{
 4 
 5     private static final long serialVersionUID = -7056841418193254583L;
 6 
 7     private String address;
 8     private String text;
 9     public EmailEvent(Object source) {
10         super(source);
11     }
12     public String getAddress() {
13         return address;
14     }
15     public void setAddress(String address) {
16         this.address = address;
17     }
18     public String getText() {
19         return text;
20     }
21     public void setText(String text) {
22         this.text = text;
23     }
24     
25 }

  上面的EmailEvent類繼承了ApplicationContext類,除此之外,它就是一個普通的Java類。

  容器的監聽器必須實現ApplicationListener接口,實現該接口必須實現如下方法:

  》onApplicationEvent(ApplicationEvent event):每當容器內發生任何事件時,此方法都被觸發。

  本例所用的監聽器代碼如下:

 1 import org.springframework.context.ApplicationEvent;
 2 import org.springframework.context.ApplicationListener;
 3 
 4 public class EmailNotifier implements ApplicationListener<ApplicationEvent>{
 5 
 6     //該方法會在容器發生事件時自動觸發
 7     public void onApplicationEvent(ApplicationEvent event) {
 8         if(event instanceof EmailEvent){
 9             //只處理EmailEvent,發送Email通知...
10             EmailEvent emailEvent = (EmailEvent)event;
11             System.out.println("需要發送的郵件的接收地址:"+emailEvent.getAddress());
12             System.out.println("需要發送郵件的郵件正文:"+emailEvent.getText());
13         }else{
14             //容器內置時間不做任何處理
15             System.out.println("容器本身事件: "+event);
16         }
17     }
18 
19 }

  將監聽器配置在容器中,配置文件如下:

1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans
3     xmlns="http://www.springframework.org/schema/beans"
4     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5     xmlns:p="http://www.springframework.org/schema/p"
6     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
7     <!-- 配置監聽器 -->
8     <bean class="com.spring_example.event.EmailNotifier" />
9 </beans>

  從上面的配置文件中可以看出,為Spring容器注冊事件監聽器,不需要像AWT編程那樣采用代碼進行編程,只要進行簡單的配置即可。當我們在Spring配置了一個實現ApplicationListener的Bean。Springl容器就會把這個Bean當初容器的監聽器。

  當系統創建Spring容器,加載Spring容器時會自動觸發容器事件,容器事件監聽器可以監聽到這些事件。除此之外,程序也可調用ApplicationContext的publishEvent方法來主動觸發容器事件。如下主程序使用ApplicationContext的publishEvent來觸發事件。

1         ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
2         //創建一個ApplicationEvent對象
3         EmailEvent ele = new EmailEvent("Hello");
4         ele.setAddress("123456@163.com");
5         ele.setText("Hello World");
6         //主動觸發容器事件
7         ac.publishEvent(ele);

  上面的代碼通過ApplicationContext對象的publishEvent主動觸發該事件。運行上面的程序將看到如下執行結果。

1 容器本身事件: org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@141b571: startup date [Fri Sep 13 10:16:01 CST 2013]; root of context hierarchy]
2 需要發送的郵件的接收地址:123456@163.com
3 需要發送郵件的郵件正文:Hello World

  從上面的執行結果可以看出,監聽器不僅監聽到程序所觸發的事件,也監聽到容器內置的事件。實際上,如果開發者需要在Spring容器初始化,銷毀時回調自定義方法,就可以通過上面的監聽器來實現。

  如果Bean想發布事件,則Bean必須獲得其容器的引用。如果程序中沒有直接獲取容器的引用,則應該讓Bean實現ApplicationContextAware 或 BeanFactoryAware接口,從而可以獲得容器的引用。

  Spring提供如下幾個內置事件:

  》ContextRefreshEvent: ApplicationContext容器初始化或刷新觸發該事件。此處的初始化是指,所有Bean 被成功裝載,后處理Bean被檢測並激發,所有Singleton Bean被預實例化,ApplicationContext容器已就緒可用。

  》ContextStartedEvent: 當使用ConfigurableApplicationContext(ApplicationContext的子接口)接口的start()方法啟動ApplicationContext容器時觸發該事件。容器管理生命周期的Bean實例將獲得一個指定的啟動信號,這在經常需要停止后重新啟動的場合比較常見。

  》ContextClosedEvent:當使用ConfigurableApplicationContext接口的close()方法關閉ApplicationContext容器時觸發該事件。

  》ContextStoppedEvent:當使用ConfigurableApplicationContext接口的stop()方法使ApplicationContext停止時觸發該事件。此處的“停止”意味着容器管理生命周期的Bean實例將獲得一個指定的停止信號,被停止的Spring容器可在此調用start()方法重新啟動。

  》RequestHandledEvent:Web相關的事件,只能運用於使用DispatcherServlet的Web運用。在使用Spring作為前端的MVC控制器時,當Spring處理用戶請求結束后,系統會自動觸發該事件。

  Spring的這種事件模型其實就是標准的觀察者設計模式。

 


免責聲明!

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



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