主要介紹spring的容器事件是如何運作的,介紹之前當然要講它遵從什麼模式,什麼是事件,廣播器等等。
五個人在報社訂閱了報紙。報社一旦有了新報紙,就派員工分別送到這五個人手裡。在這個例子中,“報紙”就是事件,“報社”就是廣播器,五個訂閱者就是監聽器。廣播器收到事件,把事件傳給監聽器,監聽器對事件做一些事情。這樣的例子屬於觀察者模式。
- 觀察者模式:A類負責接收新信息,B、C、D類一直關註著A。A類一旦有了新信息,就發送給B、C、D類,B、C、D類收到信息作出不同的操作。這就是觀察者模式。具體到代碼中,A中設置一個變數message(這就是信息),當message改變時,調用B、C、D的performMessage(message)方法(這就把message發送給B、C、D類並讓B、C、D類開始處理了。)在這裡,B、C、D類是傾聽者(相當於監聽器),而A是發佈者(相當於廣播器),message就是事件。
- java的觀察者模式:java.util.Observer屬於傾聽者介面,編寫自己的傾聽者只需要實現此介面。java.util.Observable是發佈者,編寫自己的發佈者需要擴展此類。
- 事件體系:有下麵幾個要素:
- 事件:像新報紙一樣,發生了事情,這個事情就是事件。
- 事件源:事情的發起者。
- 事件廣播器:把事件通知給事件監聽器。(類似報社)。
- 事件監聽器:接收事件並針對事件做一些工作。(訂閱者分別讀了報紙後有不同的反應)。
- 事件監聽器註冊表:框架的事件監聽器都存放在註冊表裡。
- 事件體系角色圖:,事件源產生事件,把事件傳給事件廣播器,事件廣播器再把事件傳給事件監聽器註冊表中的事件監聽器。
- Spring是如何使用事件廣播器發佈事件的?
- 要發佈事件,必須有幾個要素:事件類、廣播器、監聽器。
- java.util.EventObject是java的事件類,spring的ApplicationContextEvent擴展了EventObject類。繼承關係是:,其中,ApplicationEvent繼承了EventObject。我們寫自己的spring事件類,可以擴展ApplicationEvent。
- java.util.EventListener是java的事件監聽器類,spring的ApplicationListener擴展了EventListener介面。可以擴展ApplicationListener來編寫自己的監聽器(寫好後在配置文件中配置)。
- spring的事件廣播器繼承關係:事件監聽器註冊表由事件廣播器提供。可以實現ApplicationEventMulticaster寫自己的廣播器,如果沒有自己的廣播器,spring將使用預設的SimpleApplicationEventMulticaster廣播器。 事件類、監聽器類、廣播器類都具備了,再寫一個事件源類(製造事件,必須實現ApplicationContextAware介面,覆蓋setApplicationContext方法,從而獲取ApplicationContext實例。寫好後在配置文件中配置),讓整個事件過程運作起來。具體運作過程:
- spring容器啟動時會初始化事件廣播器,同時事件廣播器提供了監聽器註冊表。
- spring根據配置文件獲取所有監聽器並放到監聽器註冊表中。
- spring容器啟動完成後運行事件源類,製造事件,並把事件傳給廣播器,廣播器再把事件傳給監聽器。
- 一個實例:
- 編寫事件類:
public class MailSendEvent extends ApplicationContextEvent { private String to; public MailSendEvent(ApplicationContext source, String to) { super(source); this.to = to; } public String getTo() { return this.to; } }
- 編寫事件監聽器類:
public class MailSendListener implements ApplicationListener<MailSendEvent>{ public void onApplicationEvent(MailSendEvent event) { MailSendEvent mse = (MailSendEvent) event; System.out.println("MailSendListener:向" + mse.getTo() + "發送完一封郵件"); } }
- 編寫事件源類(spring容器啟動後載入該類驅動整個事件傳送過程)(下麵代碼中,在publishEvent(mse)內部,spring委托ApplicationEventMulticaster廣播器將事件通知給監聽器):
public class MailSender implements ApplicationContextAware { private ApplicationContext ctx ; public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.ctx = ctx; } public void sendMail(String to){ System.out.println("MailSender:模擬發送郵件..."); MailSendEvent mse = new MailSendEvent(this.ctx,to); ctx.publishEvent(mse); } }
- 在XML中配置監聽器和事件源類:
<bean class="com.baobaotao.event.MailSendListener"/> <bean id="mailSender" class="com.baobaotao.event.MailSender"/>
- 主函數中調用事件源:
public static void main(String[] args) { String resourceFile = "com/baobaotao/event/beans.xml"; ApplicationContext ctx = new ClassPathXmlApplicationContext(resourceFile); MailSender mailSender = ctx.getBean(MailSender.class); mailSender.sendMail("test mail."); System.out.println("done."); }
- 編寫事件類: