代码改变世界

spring监听器原理

  Spiderman25  阅读(24)  评论(1编辑  收藏  举报

jdk中的

 spring中的

 jdk中的

 spring中的

 

 

 

以容器加载完为例

 ServletWebServerApplicationContext

 容器上下文中发布事件

 

 

容器中持有广播器的引用

 

 

现在看下是如何找到监听器的

 

先用事件类型与来源类型作为key,从缓存中取,取到了就直接返回。如果没有取到,则new出一个ListenerRetriever,类中是类型个类型事件的监听器集合,然后把符合条件的监听器放到集合中,再把该ListenerRetriever放到缓存中。

 

 

 

复制代码
private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable AbstractApplicationEventMulticaster.ListenerRetriever retriever) {
        List<ApplicationListener<?>> allListeners = new ArrayList();
        LinkedHashSet listeners;
        LinkedHashSet listenerBeans;
        synchronized(this.retrievalMutex) {
            listeners = new LinkedHashSet(this.defaultRetriever.applicationListeners);
            listenerBeans = new LinkedHashSet(this.defaultRetriever.applicationListenerBeans);
        }

        Iterator var7 = listeners.iterator();

        while(var7.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var7.next();
            if (this.supportsEvent(listener, eventType, sourceType)) {
                if (retriever != null) {
                    retriever.applicationListeners.add(listener);
                }

                allListeners.add(listener);
            }
        }

        if (!listenerBeans.isEmpty()) {
            ConfigurableBeanFactory beanFactory = this.getBeanFactory();
            Iterator var15 = listenerBeans.iterator();

            while(var15.hasNext()) {
                String listenerBeanName = (String)var15.next();

                try {
                    if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) {
                        ApplicationListener<?> listener = (ApplicationListener)beanFactory.getBean(listenerBeanName, ApplicationListener.class);
                        if (!allListeners.contains(listener) && this.supportsEvent(listener, eventType, sourceType)) {
                            if (retriever != null) {
                                if (beanFactory.isSingleton(listenerBeanName)) {
                                    retriever.applicationListeners.add(listener);
                                } else {
                                    retriever.applicationListenerBeans.add(listenerBeanName);
                                }
                            }

                            allListeners.add(listener);
                        }
                    } else {
                        Object listener = beanFactory.getSingleton(listenerBeanName);
                        if (retriever != null) {
                            retriever.applicationListeners.remove(listener);
                        }

                        allListeners.remove(listener);
                    }
                } catch (NoSuchBeanDefinitionException var11) {
                }
            }
        }

        AnnotationAwareOrderComparator.sort(allListeners);
        if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {
            retriever.applicationListeners.clear();
            retriever.applicationListeners.addAll(allListeners);
        }

        return allListeners;
    }
复制代码

 

protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {
        ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);
        return declaredEventType == null || declaredEventType.isAssignableFrom(eventType);
    }

 

if (this.supportsEvent(beanFactory, listenerBeanName, eventType)) ,这里面,为true的情况,1事件类型为GenericApplicationListener和SmartApplicationListener其中之一的实现,2事件的监听类

型与事件的类型相同(即接口ApplicationListener中的泛型参数类型相同),对于2,由于this.supportsEvent(listener, eventType, sourceType)这里会继续用到了适配器,所以肯定true,而对于1,则

可以不一定为true,因为这里面完全可以实现类自己自定义

protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
        GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
        return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
    }

这里面会判断是否支持该事件类型以及来源类型,如果都支持才算支持。好明显GenericApplicationListener有这两个方法,而其的监听器有可能没有,所以用到了适配器类。

复制代码
public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener {
    private static final Map<Class<?>, ResolvableType> eventTypeCache = new ConcurrentReferenceHashMap();
    private final ApplicationListener<ApplicationEvent> delegate;
    @Nullable
    private final ResolvableType declaredEventType;

    public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
        Assert.notNull(delegate, "Delegate listener must not be null");
        this.delegate = delegate;
        this.declaredEventType = resolveDeclaredEventType(this.delegate);
    }

    public void onApplicationEvent(ApplicationEvent event) {
        this.delegate.onApplicationEvent(event);
    }

    public boolean supportsEventType(ResolvableType eventType) {
        if (this.delegate instanceof SmartApplicationListener) {
            Class<? extends ApplicationEvent> eventClass = eventType.resolve();
            return eventClass != null && ((SmartApplicationListener)this.delegate).supportsEventType(eventClass);
        } else {
            return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType);
        }
    }

    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return this.supportsEventType(ResolvableType.forClass(eventType));
    }

    public boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return !(this.delegate instanceof SmartApplicationListener) || ((SmartApplicationListener)this.delegate).supportsSourceType(sourceType);
    }

    public int getOrder() {
        return this.delegate instanceof Ordered ? ((Ordered)this.delegate).getOrder() : 2147483647;
    }

    @Nullable
    private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) {
        ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
        if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) {
            Class<?> targetClass = AopUtils.getTargetClass(listener);
            if (targetClass != listener.getClass()) {
                declaredEventType = resolveDeclaredEventType(targetClass);
            }
        }

        return declaredEventType;
    }

    @Nullable
    static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
        ResolvableType eventType = (ResolvableType)eventTypeCache.get(listenerType);
        if (eventType == null) {
            eventType = ResolvableType.forClass(listenerType).as(ApplicationListener.class).getGeneric(new int[0]);
            eventTypeCache.put(listenerType, eventType);
        }

        return eventType != ResolvableType.NONE ? eventType : null;
    }
}
复制代码

这样不管是什么ApplicationListener监听器都能适配了。这里面用到了ResolvableType,这个相当于是简化反射而存在的类,可以方便取出泛型类的信息。

复制代码
private boolean supportsEvent(ConfigurableBeanFactory beanFactory, String listenerBeanName, ResolvableType eventType) {
        Class<?> listenerType = beanFactory.getType(listenerBeanName);
        if (listenerType != null && !GenericApplicationListener.class.isAssignableFrom(listenerType) && !SmartApplicationListener.class.isAssignableFrom(listenerType)) {
            if (!this.supportsEvent(listenerType, eventType)) {
                return false;
            } else {
                try {
                    BeanDefinition bd = beanFactory.getMergedBeanDefinition(listenerBeanName);
                    ResolvableType genericEventType = bd.getResolvableType().as(ApplicationListener.class).getGeneric(new int[0]);
                    return genericEventType == ResolvableType.NONE || genericEventType.isAssignableFrom(eventType);
                } catch (NoSuchBeanDefinitionException var7) {
                    return true;
                }
            }
        } else {
            return true;
        }
    }
复制代码

 上面这里是判断容器中的bean是否支持事件,bd.getResolvableType().as(ApplicationListener.class).getGeneric(new int[0])指的是当前类的父类ApplicationListener的第一个泛型参数的ResolvableType

总的来说,工厂类中有广播器,广播器里面有专门存放事件的AbstractApplicationEventMulticaster.ListenerRetriever defaultRetriever,defaultRetriever.applicationListeners不在容器中的监听器表列,defaultRetriever.applicationListenerBeans则是容器中监听器的名字列表。广播器找事件时都会从defaultRetriever和bean中两个里面找事件。后面会缓存到广播器Map<AbstractApplicationEventMulticaster.ListenerCacheKey, AbstractApplicationEventMulticaster.ListenerRetriever> retrieverCache

还有一个有意思的结论,对于GenericApplicationListener和SmartApplicationListener的实现会调用supportsEventType和supportsSourceType来判断,否则会用适配器GenericApplicationListenerAdapter

来适配,而它继承GenericApplicationListener, SmartApplicationListener,方法supportsEventType会判断是否父类的泛型为同一个,而supportsSourceType一般情况为true,除非本身要适配的对象为SmartApplicationListener实例。

defaultRetriever.applicationListeners的元素在refresh中添加,把上下文中的applicationListeners放到广播器中

defaultRetriever.applicationListenerBeans也一样在refresh中,只不过不过是从容器中找也ApplicationListener类的bean名字,然后放到广播器中(注,只是名字,后面用到的时候再取实例)

 

 

 

 

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示