org.springframework.context.support.ApplicationListenerDetector 详细介绍

server/2024/11/19 17:13:12/

一,功能介绍

early post-processor for detecting inner beans as ApplicationListeners
早期的PostProcessor用来检测并处理内部(inner)bean作为 ApplicationListeners

BeanPostProcessor that detects beans which implement the ApplicationListener interface. This catches beans that can't reliably be detected by getBeanNamesForType and related operations which only work against top-level beans.

这个BeanPostProcessor 用于检测实现了 ApplicationListener 接口的 Bean,特别是那些无法通过 getBeanNamesForType 和相关操作检测到的内部 Bean,因为getBeanNamesForType 和相关操作 只针对 top-level beans。

言外之意就是这个 BeanPostProcessor 可以帮助你确保所有实现了 ApplicationListener 接口的 Bean 都能正确地处理应用事件,即使它们是内部 Bean 或非单例作用域的 Bean。

二,如何实现

java">
/*** {@code BeanPostProcessor} that detects beans which implement the {@code ApplicationListener}* interface. This catches beans that can't reliably be detected by {@code getBeanNamesForType}* and related operations which only work against top-level beans.** <p>With standard Java serialization, this post-processor won't get serialized as part of* {@code DisposableBeanAdapter} to begin with. However, with alternative serialization* mechanisms, {@code DisposableBeanAdapter.writeReplace} might not get used at all, so we* defensively mark this post-processor's field state as {@code transient}.** @author Juergen Hoeller* @since 4.3.4*/
class ApplicationListenerDetector implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {private static final Log logger = LogFactory.getLog(ApplicationListenerDetector.class);private final transient AbstractApplicationContext applicationContext;private final transient Map<String, Boolean> singletonNames = new ConcurrentHashMap<>(256);public ApplicationListenerDetector(AbstractApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (ApplicationListener.class.isAssignableFrom(beanType)) {this.singletonNames.put(beanName, beanDefinition.isSingleton());}}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {if (bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrievalBoolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {// singleton bean (top-level or inner): register on the flythis.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}this.singletonNames.remove(beanName);}}return bean;}@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) {if (bean instanceof ApplicationListener) {try {ApplicationEventMulticaster multicaster = this.applicationContext.getApplicationEventMulticaster();multicaster.removeApplicationListener((ApplicationListener<?>) bean);multicaster.removeApplicationListenerBean(beanName);}catch (IllegalStateException ex) {// ApplicationEventMulticaster not initialized yet - no need to remove a listener}}}@Overridepublic boolean requiresDestruction(Object bean) {return (bean instanceof ApplicationListener);}@Overridepublic boolean equals(@Nullable Object other) {return (this == other || (other instanceof ApplicationListenerDetector &&this.applicationContext == ((ApplicationListenerDetector) other).applicationContext));}@Overridepublic int hashCode() {return ObjectUtils.nullSafeHashCode(this.applicationContext);}}

        1.postProcessMergedBeanDefinition

        该bean的BeanDefination合并完了之后的,如果该bean的类是ApplicationListener子类,那么先用该bean的beanName标记该bean是不是单例,这个标记在后面bean实例化之后,判断是否要将这个ApplicationListener添加到org.springframework.context.support.AbstractApplicationContext#applicationListeners 和 org.springframework.context.support.AbstractApplicationContext#applicationEventMulticaster 中的时候用到。

这里的合并是指,当一个bean指定了parent的时候,需要把 parent 中定义的信息,合并到当前bean的BeanDefination中

        2.postProcessAfterInitialization

        该bean实例化之后,并且初始化之后,判断该bean是否是一个ApplicationListener类型的实例,如果不是不做处理,如果是ApplicationListener类型的实例再判断该bean是不是单例,如果是单例,就将其添加到org.springframework.context.support.AbstractApplicationContext#applicationListeners 和 org.springframework.context.support.AbstractApplicationContext#applicationEventMulticaster 以便在事件发生时能够通知到这些监听器。

之所以判断是不是单例,是因为如果一个 ApplicationListener 是非单例作用域的内部 Bean,应用上下文无法有效地管理和广播事件给这些 Bean,因为每次请求都会创建新的实例,而这些实例不在全局范围内注册。


http://www.ppmy.cn/server/143245.html

相关文章

DDRPHY数字IC后端设计实现系列专题之数字后端floorplanpowerplan设计

3.2.3 特殊单元的布局 布图阶段除了布置 I/O 单元和宏单元&#xff0c;在 28nm 制程工艺时&#xff0c;还需要处理两种特 殊的物理单元&#xff0c;Endcap 和 Tapcell。 DDRPHY数字IC后端设计实现系列专题之后端设计导入&#xff0c;IO Ring设计 &#xff08;1&#xff09;拐…

网络安全、Web安全、渗透测试之笔经面经总结(三)

本篇文章涉及的知识点有如下几方面&#xff1a; 1.什么是WebShell? 2.什么是网络钓鱼&#xff1f; 3.你获取网络安全知识途径有哪些&#xff1f; 4.什么是CC攻击&#xff1f; 5.Web服务器被入侵后&#xff0c;怎样进行排查&#xff1f; 6.dll文件是什么意思&#xff0c;有什么…

微服务即时通讯系统的实现(客户端)----(3)

目录 1. 聊天界面逻辑1.1 发送消息1.2 接收消息 2. 个人信息详情逻辑2.1 加载个人信息2.2 修改昵称2.3 修改签名2.4 修改电话 (1) - 发起短信验证码2.5 修改电话 (2) - 修改电话逻辑2.6 修改头像 3. 用户详细信息界面逻辑3.1 获取指定用户的信息3.2 点击 "发送消息" …

前端pdf预览方案

前端pdf预览方案 pdf预览一般不需要前端生成pdf文件&#xff0c;pdf文件一般是通过接口&#xff0c;获取pdf文件【responseType:‘blob’,】或二进制文件流【responseType: ‘arraybuffer’,】或者已有的pdf文件。 前端PDF预览通常是通过读取现有的PDF文件&#xff0c;并使用…

union介绍及使用

union格式 在C中&#xff0c;union是一种特殊的数据类型&#xff0c;它允许在相同的内存位置存储不同的数据类型&#xff0c;但在任意时刻只能使用一个成员。以下是union类型的基本格式说明&#xff1a; union UnionName {memberType1 memberName1;memberType2 memberName2;m…

大语言模型提示词工程学习--写小说系列(文心一言豆包通义千问):目录

前言 我本身是从事软件开发行业&#xff0c;对计算机类的东西感兴趣&#xff0c;随着ChatGPT的爆发&#xff0c;国内大厂也纷纷推出自己的大语言模型&#xff0c;大语言模型已经逐渐进入到普通人的日常生活当中&#xff0c;为了更好的学习提示词技巧&#xff0c;通过写一篇有质…

地质旅游平台推动“旅游+地质”融合发展

2024年元旦假期&#xff0c;哈尔滨文旅市场持续火爆。据哈尔滨市文化广电和旅游局大数据测算&#xff0c;截至1月1日&#xff0c;哈尔滨市累计接待游客304.79万人次&#xff0c;实现旅游总收入59.14亿元&#xff0c;游客接待量与旅游总收入达到历史峰值。 夏有进“淄”赶烤&…

html 图片转svg 并使用svg路径来裁剪html元素

1.png转svg 工具地址: Vectorizer – 免费图像矢量化 打开svg图片,复制其中的path中的d标签的路径 查看生成的svg路径是否正确 在线SVG路径预览工具 - UU在线工具 2.在html中使用svg路径 <svg xmlns"http://www.w3.org/2000/svg" width"318px" height…