观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新,在被观察者里会维护一个观察者的集合,当被观察者的状态发生改变时会去遍历集合中的观察者去执行对应的操作。
Spring中的观察者:常用的地方是listener的实现,如ApplicationListener:
(1)ApplicationListener是观察者接口,接口中定义了onApplicationEvent方法,该方法的作用是对ApplicationEvent事件进行处理。ApplicationListener有四个实现类:
ConsoleListener,FrameworkServlet,PerformanceMonitorListener,SourceFilteringListener分别对事件做不同的处理(观察者的update操作),在这里就不详细展开。
(2)SimpleApplicationEventMulticaster是被观察者,它有个抽象父类AbstractApplicationEventMulticaster,在AbstractApplicationEventMulticaster中维护了一个applicationListeners(观察者集合),SimpleApplicationEventMulticaster通过遍历applicationListeners来执行各个listener中的onApplicationEvent,具体调用listener是通过线程池TaskExecutor来异步进行的:
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);
}
});
}
}
前面讲了
SimpleApplicationEventMulticaster通知到ApplicationListener,然而这些ApplicationListener是通过父类AbstractApplicationEventMulticaster的addApplicationListener进行注册的,在AbstractApplicationContext进行refresh操作时会去调用registerListeners方法,registerListeners再去调用AbstractApplicationEventMulticaster的addApplicationListener方法进行注册。
被观察者SimpleApplicationEventMulticaster遍历观察者ApplicationListener进行相应操作是由业务需求方(如EventPublicationInterceptor)通过调用AbstractApplicationContext的publishEvent方法触发的。EventPublicationInterceptor的invoke代码:
public Object invoke(MethodInvocation invocation) throws Throwable {
Object retVal = invocation.proceed();
ApplicationEvent event = (ApplicationEvent)
this.applicationEventClassConstructor.newInstance(new Object[] {invocation.getThis()});
this.applicationEventPublisher.publishEvent(event);
return retVal;
}
AbstractApplicationContext的
publishEvent方法:
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in context [" + getId() + "]: " + event);
}
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}