最近做一个功能,需要在整个服务器容器加载完成就触发执行,这个时候我只需要实现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的整个事件监听功能。