广播器AbstractApplicationEventMulticaster 的方法retrieveApplicationListeners获取监听器时,会通过supportsEvent(listener, eventType, sourceType)方法筛选出支持相应事件类型的监听器,如下。
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
其根本是调用监听器的supportsEventType方法和supportsSourceType方法。
但是这两个方法是定义在GenericApplicationListener接口当中的,我们知道Spring当中的监听器只需要实现ApplicationListener接口就可以了,但是ApplicationListener接口并没有supportsEventType方法和supportsSourceType方法,那么SpringBoot是如何针对这部分监听器进行是否支持事件的判断呢?
答案在上面的代码中已经给出了,那就是使用GenericApplicationListenerAdapter将监听器包装起来,使用delegate表示原始监听器对象。众所周知适配器模式有三种类型,类的适配器模式、对象的适配器模式、接口的适配器模式,其中类的适配器模式需要继承原始类会占用继承的位置,一般不用,而接口的适配器模式主要用于精简父接口多余的定义,也不适合这里使用。所以用到的是对象的适配器模式,通过聚合的方式持有原始类。
public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener {
private final ApplicationListener<ApplicationEvent> delegate;
}
另外该适配器也实现了GenericApplicationListener接口,自然就实现了supportsEventType和supportsSourceType方法,有兴趣的可以自己去阅读源码看具体这两个方法是怎么实现的。
综上,通常来讲适配器模式是用于原有系统的补充,但是这里由于supportsEventType和supportsSourceType方法不需要由用户来实现,用户只需要关心ApplicationListener接口的onApplicationEvent如何实现就足够了,所以为了统一接口使用了适配器模式,把用户的监听器适配成系统需要的监听器,这也算是适配器模式的一处妙用了。