spring事件驅動模型--觀察者模式在spring中的應用


  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方法即可

 


免責聲明!

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



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