最近做一个功能,需要在整个服务器容器加载完成就触发执行,这个时候我只需要实现ApplicationListener即可。spring的这个接口就是给一个观察的入口,可以在各个阶段去触发相应的操作。不难看出这就是典型的设计模式之观察者模式。这次我们以观察者的观点去分析一下ApplicationListener。
/** * Interface to be implemented by application event listeners. * Based on the standard {@code java.util.EventListener} interface * for the Observer design pattern. * * <p>As of Spring 3.0, an ApplicationListener can generically declare the event type * that it is interested in. When registered with a Spring ApplicationContext, events * will be filtered accordingly, with the listener getting invoked for matching event * objects only. * * @author Rod Johnson * @author Juergen Hoeller * @param <E> the specific ApplicationEvent subclass to listen to * @see org.springframework.context.event.ApplicationEventMulticaster */ public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }Rod Johnson大神也在注释里写清楚了这个功能就是基于观察者模式,并且用户可以在实现类中指定自己感兴趣的事件观察。这个就是所有观察者的抽象接口,这个接口是给客户端使用的,客户端只是对接口透明,对具体的需要通知的对象是动态注入的。一旦观察者感兴趣的事件发生,客户端就会调用接口的方法通知。 这个通知方法,就是在:org.springframework.context.event.SimpleApplicationEventMulticaster中的:
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { listener.onApplicationEvent(event); } catch (Throwable err) { errorHandler.handleError(err); } } else { listener.onApplicationEvent(event); } }这里只是通知一个观察者,具体要通知哪些观察者在该类的父类org.springframework.context.event.SimpleApplicationEventMulticaster定义一种事件类型的观察者有哪些(ApplicationListener):
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }所有的监听器的注册在org.springframework.context.support.AbstractApplicationContext的refresh()方法当中的registerListener()方法,该方法基本完成了容器的初始化:
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 listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }当容器初始化结束后就会调用finishRefresh(),该事件会触发一系列操作,其中就包括通知观察者,即监听器:
protected void publishEvent(Object event, ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } // Decorate event as an ApplicationEvent if necessary ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<Object>(this, event); if (eventType == null) { eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass()); } } // Multicast right now if possible - or lazily once the multicaster is initialized if (this.earlyApplicationEvents != null) { this.earlyApplicationEvents.add(applicationEvent); } else { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } // Publish event via parent context as well... if (this.parent != null) { if (this.parent instanceof AbstractApplicationContext) { ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); } else { this.parent.publishEvent(event); } } }以上代码是根据事件去通知对应的监听器。这里的具体情况是在finishRefresh()传入了容器加载完成事件: 这样就去调用对这个事件感兴趣的监听器。
// Publish the final event. publishEvent(new ContextRefreshedEvent(this));这里完成接口调用通知。
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { invokeListener(listener, event); } }); } else { invokeListener(listener, event); } } }这样就用观察者模式实现了spring的整个事件监听功能。