Spring之Bean的生命周期源码解析(三 Bean的创建与销毁)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: Spring之Bean的生命周期源码解析(三 Bean的创建与销毁)

一、前言

这是我Spring专栏的第八篇文章: Spring之Bean生命周期源码分析(二), 主要讲解了获取Bean的销毁, 也是Bean生命周期内的最后一步. 在看本篇文章之前建议先看一下上篇文章当做前置学习 Spring之Bean生命周期源码分析(二)

Spring专栏全部内容如下:

二、记录有销毁方法的Bean

前置信息 - 设置Bean的销毁方法

如下图所示, 我们可以在Bean方法上实现 DisposableBean接口的 destory方法, 这个方法就是 Bean销毁时所执行的方法

网络异常,图片无法展示
|

在启动类执行相应的 close方法就会对 bean对象进行销毁

网络异常,图片无法展示
|

判断当前 Bean是否存在销毁方法

Bean的销毁方法在 AbstractBeanFactory.registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd)

网络异常,图片无法展示
|

我们直接去看if判断, 有一个 requiresDestruction(bean, mbd)方法, 这个方法就是去判断你的Bean有没有销毁方法

网络异常,图片无法展示
|

DisposableBeanAdapter.hasDestroyMethod方法

首先我们进入 DisposableBeanAdapter.hasDestroyMethod方法

在这个方法里, 我用红框圈了一个判断条件, 通过方法名称就可以判断出来他是判断这个 bean的实体类上是否有bean的销毁方法的, 我们点进去看一下

网络异常,图片无法展示
|

点进去之后可以看到, 它最开始就去判断我们的 bean实体类有没有去实现接口 DisposableBean或者 AutoCloseable, 如果实现了这两个接口, 那么直接返回true, 代表着这个 bean有销毁方法

如果没有实现, 那我们接着往下面走, 可以看到它执行了一个方法 inferDestroyMethodIfNecessary, 并将其返回, 该方法详情如下图所示:

网络异常,图片无法展示
|

该方法简单讲解:

  • 通过 BeanDefinition取出指定的销毁方法名字
  • 如果没有指定
  • 在通过 BeanDefinition.getDestroyMethodName取一次
  • 如果获取到的 destroyMethodName == inferred
  • 就会去判断有没有实现 DisposableBean 接口
  • 肯定是没有实现的, 之前就已经判断过了
  • 获取当前 bean对应 类的close方法, 就把这个方法当做销毁方法
  • 如果没有找到, 就去找 shutdown方法, 把这个方法当做销毁方法
  • 最后就是两个三元运算符, 这个没什么好说的了

hasDestructionAwareBeanPostProcessors方法

这个方法就是判断当前 bean有没有销毁的逻辑

DisposableBeanAdapter.hasApplicableProcessors

调用所有的定义的销毁的 postProcessor

网络异常,图片无法展示
|

上图中的if判断有一个方法 processor.requiresDestrunction(bean) 是用来判断当前Bean的类有没有加上 @PreDestory注解, 如果有就返回 true, 就证明了, 是通过注解的方式实现了销毁方法

确定该 Bean对象有销毁方法后

确定该 Bean对象有销毁方法后就会进入下图这个判断

网络异常,图片无法展示
|

如果 BeanDefinition 对象是单例的

就会进入下面的方法

网络异常,图片无法展示
|

可以看到这个方法就是通过构造方法创建了一个 DisposableBeanAdapter实例,然后将这个实例和 beanName传进了 registerDisposableBean方法中, 我们看一下这个方法

网络异常,图片无法展示
|

可以看到, 最后就是这个beanName和创建的 DisposableBean放进了一个map中

网络异常,图片无法展示
|

如果 BeanDefinition对象不是单例的

如下图所示:

  • 如果当前 BeanDefinition不是单例的
  • 那么会取出当前 BeanDefinition的Scope类型
  • 并执行对应的 registerDestructionCallback方法

和单例一样的是, 也是传递了一个 beanName和DisposableBean类的实例

网络异常,图片无法展示
|

但是点进这个方法内部可以看到, 他的内部实现和单例的情况不一样

三、Bean的销毁

关于Bean的销毁, 我们通过容器关闭执行的 close方法点进去

网络异常,图片无法展示
|

点击去可以看到一个 doClass()方法

网络异常,图片无法展示
|

doClass方法如下图所示:

网络异常,图片无法展示
|

在这个方法里面, 也有很多知识点,我们后续会讲到, 目前主要看的方法是 destroyBeans(), 点进这个方法

网络异常,图片无法展示
|

如上图所示, 我们可以通过这个方法名称看出来, 它销毁了我们 Bean工厂内所有的单例Bean

原型Bean Spring中都没有存储, 所以不用销毁

在往下走, 我们跳转到对应的方法

网络异常,图片无法展示
|

网络异常,图片无法展示
|

super.destroySingletons();

先看它执行了它父类的方法

网络异常,图片无法展示
|

查看是否有销毁的方法

我们可以看到, 他去遍历了一个map, 这个map就是之前我们在记录销毁方法时的 map

网络异常,图片无法展示
|

在这个方法中, 可以看到还是先移除掉单例池

网络异常,图片无法展示
|

下一步执行了以下代码, 将自己从map中移除掉

disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
复制代码

最后执行了 destroyBean方法

destroyBean方法

如下图所示, 这个map表示的是, 当前bean被哪些bean依赖了, 当前bean要销毁的话, 其他的bean也要被销毁

网络异常,图片无法展示
|

这个方法比较重要的是他最后执行了 destroy方法(销毁方法)

网络异常,图片无法展示
|

清空单例池

这一步就是他去遍历所有有销毁方法, 销毁逻辑的Bean, 加入没有销毁方法的Bean, 那么就执行下面的三个clear, 清空map

网络异常,图片无法展示
|

最后执行了一个方法, 清空了单例池

网络异常,图片无法展示
|

四、总结

到这里 Bean销毁的记录和执行就结束了, 下一篇文章开始讲解Spring依赖注入相关源码



目录
相关文章
|
4天前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
44 29
|
1天前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
14 3
|
3天前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
13天前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
3天前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
11天前
|
存储 前端开发 JavaScript
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。
|
19天前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
126 0
|
1天前
|
缓存 NoSQL Java
基于SpringBoot的Redis开发实战教程
Redis在Spring Boot中的应用非常广泛,其高性能和灵活性使其成为构建高效分布式系统的理想选择。通过深入理解本文的内容,您可以更好地利用Redis的特性,为应用程序提供高效的缓存和消息处理能力。
96 79
|
23天前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
75 12
|
26天前
|
Java 应用服务中间件 Maven
SpringBoot项目打包成war包
通过上述步骤,我们成功地将一个Spring Boot应用打包成WAR文件,并部署到外部的Tomcat服务器中。这种方式适用于需要与传统Servlet容器集成的场景。
43 8

热门文章

最新文章

推荐镜像

更多