iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >SpringBoot深入分析讲解监听器模式下
  • 486
分享到

SpringBoot深入分析讲解监听器模式下

2024-04-02 19:04:59 486人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

我们来以应用启动事件:ApplicationStartingEvent为例来进行说明: 以启动类的springApplication.run方法为入口,跟进SpringApplica

我们来以应用启动事件:ApplicationStartingEvent为例来进行说明:

以启动类的springApplication.run方法为入口,跟进SpringApplication的两个同名方法后,我们会看到主要的run方法,方法比较长,在这里只贴出与监听器密切相关的关键的部分:

SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();

我们跟进这个starting方法,方法的内容如下:

void starting() {
	for (SpringApplicationRunListener listener : this.listeners) {
		listener.starting();
	}
}

这里的listeners已经在getRunListeners方法中完成了加载,加载原理类似于系统初始化器,关于系统初始化器的加载可以参考SpringBoot深入浅出分析初始化器

starting方法逻辑很简单,就是调用SpringApplicationRunListener的starting方法。下面继续分析这个starting方法:

我们进入了EventPublishingRunListener类(SpringApplicationRunListener 的实现类)的starting方法:

	@Override
	public void starting() {
		this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
	}

这里就使用了广播器,来广播新的ApplicationStartingEvent事件。

我们跟进这个multicastEvent方法:

	@Override
	public void multicastEvent(ApplicationEvent event) {
		multicastEvent(event, resolveDefaultEventType(event));
	}

继续看同名的方法multicastEvent:

	@Override
	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);
			}
		}
	}

这里的ResolvableType 是对event做了包装,我们不去关注;由于我们没有创建线程池,所以executor是空的。我们重点关注两个部分:

1、getApplicationListeners --> 获取所有关注此事件的监听器(※);

2、invokeListener --> 激活监听器;

getApplicationListeners (AbstractApplicationEventMulticaster类中)方法,代码如下:

	protected Collection<ApplicationListener<?>> getApplicationListeners(
			ApplicationEvent event, ResolvableType eventType) {
		Object source = event.getSource();
		Class<?> sourceType = (source != null ? source.getClass() : null);
		ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
		// Quick check for existing entry on ConcurrentHashMap...
		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 ListenerRetriever
			synchronized (this.retrievalMutex) {
				retriever = this.retrieverCache.get(cacheKey);
				if (retriever != null) {
					return retriever.getApplicationListeners();
				}
				retriever = new ListenerRetriever(true);
				Collection<ApplicationListener<?>> listeners =
						retrieveApplicationListeners(eventType, sourceType, retriever);
				this.retrieverCache.put(cacheKey, retriever);
				return listeners;
			}
		}
		else {
			// No ListenerRetriever caching -> no synchronization necessary
			return retrieveApplicationListeners(eventType, sourceType, null);
		}
	}

入参中的event就是ApplicationStartingEvent,sourceType是org.springframework.boot.SpringApplication类。ListenerRetriever类型本人将其视作是一个保存监听器的容器

可以看出,程序首先在缓存里面寻找ListenerRetriever类型的retriever,如果没有找到,加再从缓存里面找一次。这里我们缓存里是没有内容的,所以都不会返回。

接下来调用了retrieveApplicationListeners方法,来遍历所有的监听器。retrieveApplicationListeners方法比较长,我们重点关注下supportsEvent(listener, eventType, sourceType)方法,该方法用来判断是否此监听器关注该事件,过程主要包括,判断此类型是否是GenericApplicationListener类型,如果不是,则构造一个代理,代理的目的是,通过泛型解析,最终获得监听器所感兴趣的事件。

如果经过判断,监听器对该事件是感兴趣的,则此监听器会被加入监听器列表中。

	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));
	}

当某个事件所有的监听器被收集完毕后,multicastEvent(SimpleApplicationEventMulticaster类)方法会对事件进行传播。即调用监听器的通用触发接口方法:listener.onApplicationEvent(event);这样,就完成了这个事件的传播。

上一篇

到此这篇关于SpringBoot深入分析讲解监听器模式下的文章就介绍到这了,更多相关SpringBoot监听器模式内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: SpringBoot深入分析讲解监听器模式下

本文链接: https://www.lsjlt.com/news/164307.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot深入分析讲解监听器模式下
    我们来以应用启动事件:ApplicationStartingEvent为例来进行说明: 以启动类的SpringApplication.run方法为入口,跟进SpringApplica...
    99+
    2024-04-02
  • SpringBoot深入分析讲解监听器模式上
    目录1、事件ApplicationEvent2、监听器ApplicationListener3、事件广播器ApplicationEventMulticaster 注:图片来源于网络 ...
    99+
    2024-04-02
  • SpringBoot监听器模式实例分析
    本篇内容主要讲解“SpringBoot监听器模式实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot监听器模式实例分析”吧!1、事件ApplicationEventAppl...
    99+
    2023-07-02
  • 深入讲解下Rust模块使用方式
    目录前言模块声明&使用方法一:直接在根文件下声明 add.rs方法二:声明add文件夹,文件夹下包含 mod.rs方法三:add.rs和add文件夹同时存在同模块相邻文件引用...
    99+
    2024-04-02
  • SpringBoot监听器模式怎么实现
    本篇内容介绍了“SpringBoot监听器模式怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!我们来以应用启动事件:Applicati...
    99+
    2023-07-02
  • SpringBoot深入分析讲解日期时间处理
    目录GET请求及POST表单日期时间字符串格式转换使用自定义参数转换器(Converter)使用Spring注解使用ControllerAdvice配合initBinderJSON入...
    99+
    2024-04-02
  • RocketMq深入分析讲解两种削峰方式
    目录何时需要削峰通过消息队列的削峰方法有两种消费延时控流总结何时需要削峰 当上游调用下游服务速率高于下游服务接口QPS时,那么如果不对调用速率进行控制,那么会发生很多失败请求 通过消...
    99+
    2023-01-28
    RocketMq削峰 RocketMq削峰方式 RocketMq削峰代码
  • C++深入分析讲解链表
    目录链表的概述1、数组特点2、链表的概述3、链表的特点静态链表链表的操作1、链表插入节点头部之前插入节点尾部之后插入节点有序插入节点2、遍历链表节点3、查询指定节点4、删除指定节点5...
    99+
    2024-04-02
  • JavaHashMap源码深入分析讲解
    1.HashMap是数组+链表(红黑树)的数据结构。 数组用来存放HashMap的Key,链表、红黑树用来存放HashMap的value。 2.HashMap大小的确定: 1) Ha...
    99+
    2024-04-02
  • Golangsync.Map原理深入分析讲解
    目录GO语言内置的mapsync.Mapsync.Map原理分析sync.Map的结构查找新增和更新删除GO语言内置的map go语言内置一个map数据结构,使用起来非常方便,但是它...
    99+
    2022-12-17
    Go sync.Map Golang sync.Map原理
  • Java设计模式之单件模式深入讲解
    目录定义Java单件模式经典单件模式的实现多线程单件模式的实现急切创建实例双重检查加锁Python单件模式模块实现new关键字实现装饰器实现函数装饰器类装饰器定义 单件模式确保一个类...
    99+
    2024-04-02
  • Java深入浅出讲解代理模式
    目录1、动态代理模式2、JDK动态代理3、JDK动态代理代码演示1、动态代理模式 动态代理的特点: 当代理对象的时候,不需要实现接口代理对象的生成,是利用JDK的API,动态的在内存...
    99+
    2024-04-02
  • Java 代码实例解析设计模式之监听者模式
    代码展示 Main:测试类 ObServer:每个被监听的对象实现该接口,重写该方法,完成自己的业务 public interface ObServer { ...
    99+
    2024-04-02
  • SpringBoot自动配置源码深入刨析讲解
    目录自动配置底层源码分析总结自动配置底层源码分析 本次springboot源码来自2.6.6版本。 @EnableAutoConfiguration源码解析 在springboot中...
    99+
    2024-04-02
  • Python魔术方法深入分析讲解
    目录前言__init____new____call____del____str__总结前言 魔术方法就是一个类/对象中的方法,和普通方法唯一的不同是:普通方法需要调用,而魔术方法是在...
    99+
    2023-02-08
    Python魔术方法 Python魔术方法原理
  • ReactHooks核心原理深入分析讲解
    目录Hooks闭包开始动手实现将useState应用到组件中过期闭包模块模式实现useEffect支持多个HooksCustom Hooks重新理解Hooks规则React Hook...
    99+
    2022-12-17
    React Hooks React Hooks原理
  • C++深入分析讲解智能指针
    目录1.简介2.unique_ptr指针(独占指针)3.shared_ptr指针(共享所有权)4.weak_ptr(辅助作用)5.自实现初级版智能指针6.总结1.简介 程序运行时存在...
    99+
    2024-04-02
  • Java深入分析讲解反射机制
    目录反射的概述获取Class对象的三种方式通过反射机制获取类的属性通过反射机制访问Java对象的属性反射机制与属性配置文件的配合使用资源绑定器配合使用样例通过反射机制获取类中方法通过...
    99+
    2024-04-02
  • Spring深入分析讲解BeanUtils的实现
    目录背景DOBODTOVO数据实体转换使用方式原理&源码分析属性赋值类型擦除总结背景 DO DO是Data Object的简写,叫做数据实体,既然是数据实体,那么也就是和存储...
    99+
    2024-04-02
  • Android权限机制深入分析讲解
    目录1、权限2、在程序运行时申请权限1、权限 普通权限:不会直接威胁到用户安全和隐私的权限危险权限:那些可能会触及用户隐私或者对设备安全性造成影响的权限。 到Android 10 系...
    99+
    2022-12-08
    Android权限机制 Android权限管理 Kotlin权限机制
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作