spring中的事件驅(qū)動(dòng)模型也叫作發(fā)布訂閱模式,是觀察者模式的一個(gè)典型的應(yīng)用,關(guān)于觀察者模式在之前的博文中總結(jié)過(guò),http://www.cnblogs.com/fingerboy/p/5468994.html 這里主要講一下Spring中的觀察者模式的應(yīng)用. spring事件驅(qū)動(dòng)模型的結(jié)構(gòu).
首先明確幾個(gè)spring提供的類的概念 1.ApplicationEventpublic abstract class ApplicationEvent extends EventObject { private static final long serialVersionUID = 7099057708183571937L; private final long timestamp; public ApplicationEvent(Object source) { super(source); this.timestamp = System.currentTimeMillis(); } public final long getTimestamp() { return this.timestamp; } } ApplicationEvent繼承自jdk的EventObject,所有的事件都需要繼承ApplicationEvent,并且通過(guò)source得到事件源.該類的實(shí)現(xiàn)類ApplicationContextEvent表示ApplicaitonContext的容器事件. 2.ApplicationListenerpublic interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E event); } ApplicationListener繼承自jdk的EventListener,所有的監(jiān)聽(tīng)器都要實(shí)現(xiàn)這個(gè)接口,這個(gè)接口只有一個(gè)onApplicationEvent()方法,該方法接受一個(gè)ApplicationEvent或其子類對(duì)象作為參數(shù),在方法體中,可以通過(guò)不同對(duì)Event類的判斷來(lái)進(jìn)行相應(yīng)的處理.當(dāng)事件觸發(fā)時(shí)所有的監(jiān)聽(tīng)器都會(huì)收到消息,如果你需要對(duì)監(jiān)聽(tīng)器的接收順序有要求,可是實(shí)現(xiàn)該接口的一個(gè)實(shí)現(xiàn)SmartApplicationListener,通過(guò)這個(gè)接口可以指定監(jiān)聽(tīng)器接收事件的順序. 3.ApplicationContext事件機(jī)制的實(shí)現(xiàn)需要三個(gè)部分,事件源,事件,事件監(jiān)聽(tīng)器,在上面介紹的ApplicationEvent就相當(dāng)于事件,ApplicationListener相當(dāng)于事件監(jiān)聽(tīng)器,這里的事件源說(shuō)的就是applicaitonContext. ApplicationContext是spring中的全局容器,翻譯過(guò)來(lái)是"應(yīng)用上下文"的意思,它用來(lái)負(fù)責(zé)讀取bean的配置文檔,管理bean的加載,維護(hù)bean之間的依賴關(guān)系,可以說(shuō)是負(fù)責(zé)bean的整個(gè)生命周期,再通俗一點(diǎn)就是我們平時(shí)所說(shuō)的IOC容器. Application作為一個(gè)事件源,需要顯示的調(diào)用publishEvent方法,傳入一個(gè)ApplicationEvent的實(shí)現(xiàn)類對(duì)象作為參數(shù),每當(dāng)ApplicationContext發(fā)布ApplicationEvent時(shí),所有的ApplicationListener就會(huì)被自動(dòng)的觸發(fā). ApplicationContext接口實(shí)現(xiàn)了ApplicationEventPublisher接口,后者有一個(gè)很重要的方法: public interface ApplicationEventPublisher { void publishEvent(ApplicationEvent event); } 我們常用的ApplicationContext都繼承了AbstractApplicationContext,像我們平時(shí)常見(jiàn)的ClassPathXmlApplicationContext,、XmlWebApplicationContex也都是繼承了它,AbstractApplicationcontext是ApplicationContext接口的抽象實(shí)現(xiàn)類,在該類中實(shí)現(xiàn)了publishEvent方法 public void publishEvent(ApplicationEvent event) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } getApplicationEventMulticaster().multicastEvent(event); if (this.parent != null) { this.parent.publishEvent(event); } } 在這個(gè)方法中,我們看到了一個(gè)getApplicationEventMulticaster().這就要牽扯到另一個(gè)類ApplicationEventMulticaster. 4.ApplicationEventMulticaster屬于事件廣播器,它的作用是把Applicationcontext發(fā)布的Event廣播給所有的監(jiān)聽(tīng)器. 在AbstractApplicationcontext中有一個(gè)applicationEventMulticaster的成員變量,提供了監(jiān)聽(tīng)器Listener的注冊(cè)方法. public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean { private ApplicationEventMulticaster applicationEventMulticaster; protected void registerListeners() { // Register statically specified listeners first. for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String lisName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(lisName); } } } 在Spring 中使用事件監(jiān)聽(tīng)機(jī)制的Demo1. 建立事件類,繼承applicationEvent public class MyEvent extends ApplicationEvent { public MyEvent(Object source) { super(source); System.out.println("my Event"); } public void print(){ System.out.println("hello spring event[MyEvent]"); } } 2.建立監(jiān)聽(tīng)類,實(shí)現(xiàn)ApplicationListener接口 public class MyListener implements ApplicationListener{ public void onApplicationEvent(ApplicationEvent event) { if(event instanceof MyEvent){ System.out.println("into My Listener"); MyEvent myEvent=(MyEvent)event; myEvent.print(); } } } 這里再建一個(gè)監(jiān)聽(tīng)類 public class MyListener implements ApplicationListener{ public void onApplicationEvent(ApplicationEvent event) { if(event instanceof MyEvent){ System.out.println("into My Listener"); MyEvent myEvent=(MyEvent)event; myEvent.print(); } } } 3.創(chuàng)建一個(gè)發(fā)布事件的類,該類實(shí)現(xiàn)ApplicationContextAware接口,得到ApplicationContext對(duì)象,使用該對(duì)象的publishEvent方法發(fā)布事件. public class MyPubisher implements ApplicationContextAware { private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext=applicationContext; } public void publishEvent(ApplicationEvent event){ System.out.println("into My Publisher's method"); applicationContext.publishEvent(event); } } 3.在spring配置文件中,注冊(cè)事件類和監(jiān)聽(tīng)類,當(dāng)然使用注解的方式也是一樣的.(略) 4.測(cè)試 public class MyTest { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("classpath:spring/application-database.xml"); MyPubisher myPubisher=(MyPubisher) context.getBean("myPublisher"); myPubisher.publishEvent(new MyEvent("1")); } } 查看控制臺(tái)打印
總結(jié)spring的事件驅(qū)動(dòng)模型使用的是 觀察者模式 通過(guò)ApplicationEvent抽象類和ApplicationListener接口,可以實(shí)現(xiàn)ApplicationContext事件處理 監(jiān)聽(tīng)器在處理Event時(shí),通常會(huì)進(jìn)行判斷傳入的Event是不是自己所想要處理的,使用instanceof關(guān)鍵字 ApplicationEventMulticaster事件廣播器實(shí)現(xiàn)了監(jiān)聽(tīng)器的注冊(cè),一般不需要我們實(shí)現(xiàn),只需要顯示的調(diào)用applicationcontext.publisherEvent方法即可
|
|
來(lái)自: WindySky > 《事件驅(qū)動(dòng)編程》