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事件進行處理。