当前位置: 首页 > news >正文

十一、Spring源码学习之registerListeners方法

registerListeners()方法

protected void registerListeners() {// Register statically specified listeners first.//获取容器中事件监听并存放到多播器中 applicationListenersfor (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);//从容器中获取事件监听的beanName 存放到多播器中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 (!CollectionUtils.isEmpty(earlyEventsToProcess)) {for (ApplicationEvent earlyEvent : earlyEventsToProcess) {getApplicationEventMulticaster().multicastEvent(earlyEvent);}}}

SimpleApplicationEventMulticaster#multicastEvent()方法

public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));Executor executor = getTaskExecutor();for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {ErrorHandler errorHandler = getErrorHandler();if (errorHandler != null) {try {doInvokeListener(listener, event);}catch (Throwable err) {errorHandler.handleError(err);}}else {doInvokeListener(listener, event);}}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {try {//调用监听器的onApplicationEvent方法执行listener.onApplicationEvent(event);}catch (ClassCastException ex) {String msg = ex.getMessage();if (msg == null || matchesClassCastMessage(msg, event.getClass())) {// Possibly a lambda-defined listener which we could not resolve the generic event type for// -> let's suppress the exception and just log a debug message.Log logger = LogFactory.getLog(getClass());if (logger.isTraceEnabled()) {logger.trace("Non-matching event type for listener: " + listener, ex);}}else {throw ex;}}}

AbstractApplicationEventMulticaster#getApplicationListeners()方法

protected Collection<ApplicationListener<?>> getApplicationListeners(ApplicationEvent event, ResolvableType eventType) {Object source = event.getSource();Class<?> sourceType = (source != null ? source.getClass() : null);//根据事件sourceType和事件Type 构建缓存keyListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);// Quick check for existing entry on ConcurrentHashMap...//根据key从retrieverCache缓存中获取ListenerRetriever//获取监听该事件的所有监听器ListenerRetriever retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {//如果缓存中存在,则返回所有的监听器return retriever.getApplicationListeners();}if (this.beanClassLoader == null ||(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {// Fully synchronized building and caching of a ListenerRetrieversynchronized (this.retrievalMutex) {//再次从缓存中获取,防止重复加载retriever = this.retrieverCache.get(cacheKey);if (retriever != null) {return retriever.getApplicationListeners();}retriever = new ListenerRetriever(true);//根据事件Type和目标sourceType 及缓存 获取符合条件的监听器,并且将监听器放到缓存中Collection<ApplicationListener<?>> listeners =retrieveApplicationListeners(eventType, sourceType, retriever);this.retrieverCache.put(cacheKey, retriever);return listeners;}}else {// No ListenerRetriever caching -> no synchronization necessaryreturn retrieveApplicationListeners(eventType, sourceType, null);}}

AbstractApplicationEventMulticaster#retrieveApplicationListeners()方法

private Collection<ApplicationListener<?>> retrieveApplicationListeners(ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable ListenerRetriever retriever) {List<ApplicationListener<?>> allListeners = new ArrayList<>();Set<ApplicationListener<?>> listeners;Set<String> listenerBeans;synchronized (this.retrievalMutex) {//将已经存在的所有监听器和beanName 存放到临时集合中listeners = new LinkedHashSet<>(this.defaultRetriever.applicationListeners);listenerBeans = new LinkedHashSet<>(this.defaultRetriever.applicationListenerBeans);}//遍历所有的监听器for (ApplicationListener<?> listener : listeners) {//判断当前监听器是否监听eventType事件if (supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {//是 则放入缓存retriever.applicationListeners.add(listener);}allListeners.add(listener);}}if (!listenerBeans.isEmpty()) {BeanFactory beanFactory = getBeanFactory();for (String listenerBeanName : listenerBeans) {try {//遍历所有的监听器beanNameClass<?> listenerType = beanFactory.getType(listenerBeanName);//判断监听器是否监听了该事件if (listenerType == null || supportsEvent(listenerType, eventType)) {//拿到该监听器ApplicationListener<?> listener =beanFactory.getBean(listenerBeanName, ApplicationListener.class);//如果 allListeners中不存在 && 该监听器确实监听该事件if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {if (retriever != null) {//并且该事件是单例beanif (beanFactory.isSingleton(listenerBeanName)) {//则放入缓存中retriever.applicationListeners.add(listener);}else {retriever.applicationListenerBeans.add(listenerBeanName);}}allListeners.add(listener);}}}catch (NoSuchBeanDefinitionException ex) {// Singleton listener instance (without backing bean definition) disappeared -// probably in the middle of the destruction phase}}}AnnotationAwareOrderComparator.sort(allListeners);//如果缓存对象不是null && applicationListenerBeans是空的if (retriever != null && retriever.applicationListenerBeans.isEmpty()) {retriever.applicationListeners.clear();//则将该所有符合条件的监听器放入缓存中retriever.applicationListeners.addAll(allListeners);}return allListeners;}
//当前事件是否被当前监听器监听
protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {if (GenericApplicationListener.class.isAssignableFrom(listenerType) ||SmartApplicationListener.class.isAssignableFrom(listenerType)) {return true;}ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));}
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));}

相关文章:

  • 2024华为软件精英挑战赛记录
  • consul集群部署三server一client
  • macOS Sonoma如何查看隐藏文件
  • CMakeLists生成动态库.so和静态库.a
  • SnapGene 5 for Mac 分子生物学软件
  • 某某消消乐增加步数漏洞分析
  • LeetCode 406. 根据身高重建队列
  • STM32G473之flash存储结构汇总
  • 工业边缘计算网关在工业中的应用以及其为工业生产带来的效益-天拓四方
  • 【WebJs 爬虫】逆向进阶技术必知必会
  • SpringMVC设置全局异常处理器
  • [flume$2]记录一个写自定义Flume拦截器遇到的错误
  • 蓝桥杯-卡片换位
  • 设计模式学习笔记 - 设计模式与范式 -结构型:7.享元模式(上):享元模式原理和应用
  • Web Components使用(一)
  • 230. Kth Smallest Element in a BST
  • 3.7、@ResponseBody 和 @RestController
  • Asm.js的简单介绍
  • JSONP原理
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 高性能JavaScript阅读简记(三)
  • 那些年我们用过的显示性能指标
  • 浅谈Golang中select的用法
  • 要让cordova项目适配iphoneX + ios11.4,总共要几步?三步
  • 责任链模式的两种实现
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • 阿里云API、SDK和CLI应用实践方案
  • ​iOS实时查看App运行日志
  • ​低代码平台的核心价值与优势
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • ​软考-高级-系统架构设计师教程(清华第2版)【第20章 系统架构设计师论文写作要点(P717~728)-思维导图】​
  • (09)Hive——CTE 公共表达式
  • (2021|NIPS,扩散,无条件分数估计,条件分数估计)无分类器引导扩散
  • (zt)最盛行的警世狂言(爆笑)
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)php投票系统 毕业设计 121500
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (六)软件测试分工
  • (转)winform之ListView
  • .java 9 找不到符号_java找不到符号
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .net反混淆脱壳工具de4dot的使用
  • .net连接oracle数据库
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • [14]内置对象
  • [Angular] 笔记 7:模块
  • [Avalon] Avalon中的Conditional Formatting.
  • [Django 0-1] Core.Email 模块
  • [echarts] y轴不显示0
  • [Hive] CTE 通用表达式 WITH关键字