Spring事件體系

來源:互聯網
上載者:User
   Spring事件體系包括三個組件:事件,事件監聽器,事件廣播器。



事件:ApplicationEvent事件監聽器:ApplicationListener,對監聽到的事件進行處理。事件廣播器:ApplicationEventMulticaster,將Springpublish的事件廣播給所有的監聽器。Spring在ApplicationContext介面的抽象實作類別AbstractApplicationContext中完成了事件體系的搭建。AbstractApplicationContext擁有一個applicationEventMulticaster成員變 量,applicationEventMulticaster提供了容器監聽器的註冊表。AbstractApplicationContext在refresh()這個容器啟動方法中搭建了事件的基礎設施。
try {     // Invoke factory processors registered as beans in the context.     invokeBeanFactoryPostProcessors();     // Register bean processors that intercept bean creation.     registerBeanPostProcessors();     // Initialize message source for this context.     initMessageSource();     // Initialize event multicaster for this context.     initApplicationEventMulticaster();     // Initialize other special beans in specific context subclasses.     onRefresh();     // Check for listener beans and register them.     registerListeners();     // Instantiate singletons this late to allow them to access the message source.     beanFactory.preInstantiateSingletons();     // Last step: publish corresponding event.     publishEvent( new ContextRefreshedEvent( this));}

1、事件廣播器的初始化:

private void initApplicationEventMulticaster() throws BeansException {      if (containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME )) {           this.applicationEventMulticaster = (ApplicationEventMulticaster)                   getBean( APPLICATION_EVENT_MULTICASTER_BEAN_NAME ,                                  ApplicationEventMulticaster.class );           if (logger.isInfoEnabled()) {                   logger.info("Using ApplicationEventMulticaster ["                                      + this. applicationEventMulticaster + "]" );            }       }       else {           this.applicationEventMulticaster = new SimpleApplicationEventMulticaster();           if (logger.isInfoEnabled()) {               logger.info("Unable to locate ApplicationEventMulticaster with name '"+                        APPLICATION_EVENT_MULTICASTER_BEAN_NAME +                        "': using default [" + this .applicationEventMulticaster + "]");            }       } }
 使用者可以在設定檔中為容器定義一個自訂的事件廣播器,只要實現ApplicationEventMulticaster就可以了,Spring會通過 反射的機制將其註冊成容器的事件廣播器,如果沒有找到配置的外來事件廣播器,Spring自動使用 SimpleApplicationEventMulticaster作為事件廣播器。2、註冊事件監聽器
private void registerListeners () throws BeansException {   // Do not initialize FactoryBeans here: We need to leave all regular beans   // uninitialized to let post-processors apply to them!  Collection listeners = getBeansOfType(ApplicationListener.class,true,false).values();   for (Iterator it = listeners.iterator(); it.hasNext();) {         addListener((ApplicationListener) it.next());    }}protected void addListener(ApplicationListener listener) {     getApplicationEventMulticaster().addApplicationListener(listener);}
 Spring根據反射機制,使用ListableBeanFactory的getBeansOfType方法,從BeanDefinitionRegistry中找出所有實現 org.springframework.context.ApplicationListener的Bean,將它們註冊為容器的事件監聽器,實際的操作就是將其添加到事件廣播器所提供的監聽器註冊表中。3、發布事件
public void publishEvent(ApplicationEvent event) {      Assert. notNull(event, "Event must not be null");      if (logger .isDebugEnabled()) {            logger .debug("Publishing event in context ["                       + getDisplayName() + "]: " + event);      }      getApplicationEventMulticaster(). multicastEvent(event);      if (this .parent != null) {           this .parent .publishEvent(event);      }}
在AbstractApplicationContext的publishEvent方法中, Spring委託ApplicationEventMulticaster將事件通知給所有的事件監聽器4、Spring預設的事件廣播器SimpleApplicationEventMulticaster
public void multicastEvent( final ApplicationEvent event) {     for (Iterator it = getApplicationListeners().iterator(); it.hasNext();) {           final ApplicationListener listener = (ApplicationListener) it.next();           getTaskExecutor().execute( new Runnable() {                   public void run() {                          listener.onApplicationEvent(event);                   }            });      } }
遍曆註冊的每個監聽器,並啟動來調用每個監聽器的onApplicationEvent方法。由於SimpleApplicationEventMulticaster的taskExecutor的實作類別是SyncTaskExecutor,因此,事件監聽器對事件的處理,是同步進行的。從代碼可以看出,applicationContext.publishEvent()方法,需要同步等待各個監聽器處理完之後,才返回。也就是說,Spring提供的事件機制,預設是同步的。如果想用非同步,可以自己實現ApplicationEventMulticaster介面,並在Spring容器中註冊id為applicationEventMulticaster的Bean。
例子:
public class AsyncApplicationEventMulticaster extends AbstractApplicationEventMulticaster {    private TaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();    public void setTaskExecutor(TaskExecutor taskExecutor) {        this.taskExecutor = (taskExecutor != null ? taskExecutor : new SimpleAsyncTaskExecutor());    }    protected TaskExecutor getTaskExecutor() {        return this.taskExecutor;    }    @SuppressWarnings("unchecked")    public void multicastEvent(final ApplicationEvent event) {        for (Iterator<ApplicationListener> it = getApplicationListeners().iterator(); it.hasNext();) {            final ApplicationListener listener =  it.next();            getTaskExecutor().execute(new Runnable() {                public void run() {                    listener.onApplicationEvent(event);                }            });        }    }}

spring配置:

<bean id="applicationEventMulticaster"           class="com.alibaba.chj.event.AsyncApplicationEventMulticaster" />

Spring發布事件之後,所有註冊的事件監聽器,都會收到該事件,因此,事件監聽器在處理事件時,需要先判斷該事件是否是自己關心的。Sping事件體系所使用的設計模式是:觀察者模式。ApplicationListener是觀察者介面,介面中定義了onApplicationEvent方法,該方法的作用是對ApplicationEvent事件進行處理。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.