spring监听器原理
2024-01-23 18:07 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名字,然后放到广播器中(注,只是名字,后面用到的时候再取实例)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架