spring中的事件驅動模型也叫作發布訂閱模式,是觀察者模式的一個典型的應用,關於觀察者模式在之前的博文中總結過,http://www.cnblogs.com/fingerboy/p/5468994.html 這里主要講一下Spring中的觀察者模式的應用.
spring事件驅動模型的結構.
首先明確幾個spring提供的類的概念
1.ApplicationEvent
public 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,並且通過source得到事件源.該類的實現類ApplicationContextEvent表示ApplicaitonContext的容器事件.
2.ApplicationListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E event); }
ApplicationListener繼承自jdk的EventListener,所有的監聽器都要實現這個接口,這個接口只有一個onApplicationEvent()方法,該方法接受一個ApplicationEvent或其子類對象作為參數,在方法體中,可以通過不同對Event類的判斷來進行相應的處理.當事件觸發時所有的監聽器都會收到消息,如果你需要對監聽器的接收順序有要求,可是實現該接口的一個實現SmartApplicationListener,通過這個接口可以指定監聽器接收事件的順序.
3.ApplicationContext
事件機制的實現需要三個部分,事件源,事件,事件監聽器,在上面介紹的ApplicationEvent就相當於事件,ApplicationListener相當於事件監聽器,這里的事件源說的就是applicaitonContext.
ApplicationContext是spring中的全局容器,翻譯過來是"應用上下文"的意思,它用來負責讀取bean的配置文檔,管理bean的加載,維護bean之間的依賴關系,可以說是負責bean的整個生命周期,再通俗一點就是我們平時所說的IOC容器.
Application作為一個事件源,需要顯示的調用publishEvent方法,傳入一個ApplicationEvent的實現類對象作為參數,每當ApplicationContext發布ApplicationEvent時,所有的ApplicationListener就會被自動的觸發.
ApplicationContext接口實現了ApplicationEventPublisher接口,后者有一個很重要的方法:
public interface ApplicationEventPublisher { void publishEvent(ApplicationEvent event); }
我們常用的ApplicationContext都繼承了AbstractApplicationContext,像我們平時常見的ClassPathXmlApplicationContext、XmlWebApplicationContex也都是繼承了它,AbstractApplicationcontext是ApplicationContext接口的抽象實現類,在該類中實現了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); } }
在這個方法中,我們看到了一個getApplicationEventMulticaster().這就要牽扯到另一個類ApplicationEventMulticaster.
4.ApplicationEventMulticaster
屬於事件廣播器,它的作用是把Applicationcontext發布的Event廣播給所有的監聽器.
在AbstractApplicationcontext中有一個applicationEventMulticaster的成員變量,提供了監聽器Listener的注冊方法.
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 中使用事件監聽機制的Demo
1. 建立事件類,繼承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.建立監聽類,實現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(); } } }
這里再建一個監聽類
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.創建一個發布事件的類,該類實現ApplicationContextAware接口,得到ApplicationContext對象,使用該對象的publishEvent方法發布事件.
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配置文件中,注冊事件類和監聽類,當然使用注解的方式也是一樣的.(略)
4.測試
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")); } }
查看控制台打印
my Event
into My Publisher's method
into My Listener
hello spring event[MyEvent]
into My second Listener
hello spring event[MyEvent]
總結
spring的事件驅動模型使用的是 觀察者模式
通過ApplicationEvent抽象類和ApplicationListener接口,可以實現ApplicationContext事件處理
監聽器在處理Event時,通常會進行判斷傳入的Event是不是自己所想要處理的,使用instanceof關鍵字
ApplicationEventMulticaster事件廣播器實現了監聽器的注冊,一般不需要我們實現,只需要顯示的調用applicationcontext.publisherEvent方法即可