Spring源码之bean的销毁registerDisposableBeanIfNecessary方法解读
目录
- 前言
- 回顾 `doCreateBean()` 方法
- `registerDisposableBeanIfNecessary()` 方法概览
- `requiresDestruction()` 方法重点
- 给 `bean` 设置销毁方法的方式
- 检查是否有 `DestructionAwareBeanPostProcessor` 实现类
- `registerDisposableBeanIfNecessary()` 方法小结
- 什么样的 `bean` 才能销毁
- `spring` 注册关闭钩子 `ShutdownHook`
- `registerShutdownHook()` 方法
- `destroyBeans()` 方法
- `destroySingletons()` 方法
- `destroySingletons()` 方法
- `destroy()` 方法
前言
这篇文章是 IOC
容器初始化启动时,抽象类 AbstractAutowireCapableBeanFactory
的 doCreateBean()
方法里面的 registerDisposableBeanIfNecessary()
方法,它是进行 bean
的销毁的方法
阅读本篇文章,同时可以参考阅读 spring源码之getBean(获取 bean)方法解读(二) 和 Spring Aop代理对象的产生(一) 这两篇文章的 doCreateBean()
方法
回顾 doCreateBean()
方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// BeanWrapper封装了具体的Bean实例,然后可以很方便地通过调用getPropertyValue和setPropertyValue等方法反射读写Bean的具体属性BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {// 先尝试从缓存中取instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {// 调用构造方法创建一个空实例对象,并用BeanWrapper进行包装instanceWrapper = createBeanInstance(beanName, mbd, args);}final Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// 获取所有的后置处理器,如果后置处理器实现了MergedBeanDefinitionPostProcessor接口,则一次调用其postProcessMergedBeanDefinition方法synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// 如果满足循环依赖缓存条件,先缓存具体对象boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isDebugEnabled()) {logger.debug("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}/*** 循环依赖处理逻辑:将已完成实例化,但是未完成属性赋值和相关的初始化的一个不完整的 bean 添加到三级缓存 singletonFactories 中* 具体内部会遍历后置处理器,判断是否有SmartInstantiationAwareBeanPostProcessor的实现类,然后调用里面getEarlyBeanReference覆盖当前Bean* 默认不做任何操作返回当前Bean,作为拓展,这里比如可以供AOP来创建代理类*/addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// 开始对Bean实例进行初始化Object exposedObject = bean;try {// 对bean进行属性填充,在这里面完成依赖注入的相关内容populateBean(beanName, mbd, instanceWrapper);// 完成属性依赖注入后,进一步初始化Bean// 具体进行了以下操作:// 1.若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象// 2.遍历后置处理器,调用实现的postProcessBeforeInitialization方法,// 3.如果实现了initialzingBean,调用实现的 afterPropertiesSet()// 4.如果配置了init-mothod,调用相应的init方法// 5.遍历后置处理器,调用实现的postProcessAfterInitializationexposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");}}}}// 如果实现了Disposable接口,会在这里进行注册,最后在销毁的时候调用相应的destroy方法try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;
}
doCreateBean(beanName, mbd, args)
的主要方法流程:(重点)
createBeanInstance(beanName, mbd, args)
:实例化bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean))
:将已完成实例化,但是未完成属性赋值和相关的初始化的一个不完整的bean
添加到三级缓存singletonFactories
中populateBean(beanName, mbd, instanceWrapper)
:对bean
进行属性填充注入initializeBean(beanName, exposedObject, mbd)
:完成bean
的属性填充注入后,进一步初始化bean
,在此过程中产生代理对象。此时bean
的创建工作正式完成,已经可以在项目中使用了
-registerDisposableBeanIfNecessary(beanName, bean, mbd)
:如果符合bean
的销毁条件,则执行单例bean
的销毁工作
registerDisposableBeanIfNecessary()
方法概览
它的具体调用是在 AbstractBeanFactory
中的 registerDisposableBeanIfNecessary()
方法
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);// 当前 bean 的作用域不是 Prototype && requiresDestruction 返回 trueif (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {// bean 的作用域是单例的if (mbd.isSingleton()) {// Register a DisposableBean implementation that performs all destruction// work for the given bean: DestructionAwareBeanPostProcessors,// DisposableBean interface, custom destroy method.registerDisposableBean(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));}else {// A bean with a custom scope...Scope scope = this.scopes.get(mbd.getScope());if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");}scope.registerDestructionCallback(beanName,new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));}}
}
requiresDestruction()
方法重点
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {return (bean.getClass() != NullBean.class &&(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
可以看到 requiresDestruction()
方法只要满足下面任意一个即可
hasDestroyMethod()
:检查给定bean
是否有任何类型的destroy
销毁的方法可调用hasApplicableProcessors()
:检查是否有DestructionAwareBeanPostProcessor
的实现类,并且requiresDestruction()
方法返回true
给 bean
设置销毁方法的方式
- 通过
xml
文件配置destroy-method
标签属性指定的destroy
方法 - 通过注解
@Bean
可以使用属性指定销毁的方法 - 实现
DisposableBean
接口 - 销毁方法名为接口情况下, 有
close
或者shutdown
方法
检查是否有 DestructionAwareBeanPostProcessor
实现类
- 实现了
ApplicationListener
接口 - 方法加上了
@PreDestroy
注解
registerDisposableBeanIfNecessary()
方法小结
- 当
bean
的作用域不是Prototype
,同时给bean
设置了销毁方法或有DestructionAwareBeanPostProcessor
实现类 - 在满足了上述条件之后,如果
bean
的作用域是单例的时,创建DisposableBeanAdapter
进行注册(添加到disposableBeans
集合LinkedHashMap
中)
// DefaultSingletonBeanRegistry 的属性
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
什么样的 bean
才能销毁
bean
的作用域是单例时- 给
bean
设置了销毁方法或有DestructionAwareBeanPostProcessor
实现类时
spring
注册关闭钩子 ShutdownHook
spring
会先去调用注册的关闭钩子 ShutdownHook
,通过这个方式进行销毁前的动作处理
public SpringApplicationBuilder registerShutdownHook(boolean registerShutdownHook) {this.registerShutdownHookApplied = true;this.application.setRegisterShutdownHook(registerShutdownHook);return this;
}
registerShutdownHook()
方法
该方法在 AbstractApplicationContext
类中
@Override
public void registerShutdownHook() {if (this.shutdownHook == null) {// No shutdown hook registered yet.this.shutdownHook = new Thread() {@Overridepublic void run() {synchronized (startupShutdownMonitor) {// 方法调用如下doClose();}}};Runtime.getRuntime().addShutdownHook(this.shutdownHook);}
}protected void doClose() {if (this.active.get() && this.closed.compareAndSet(false, true)) {if (logger.isInfoEnabled()) {logger.info("Closing " + this);}LiveBeansView.unregisterApplicationContext(this);try {// Publish shutdown event.// 发布上下文关闭事件ContextClosedEventpublishEvent(new ContextClosedEvent(this));}catch (Throwable ex) {logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);}// Stop all Lifecycle beans, to avoid delays during individual destruction.// 调用Lifecycle#stop方法try {getLifecycleProcessor().onClose();}catch (Throwable ex) {logger.warn("Exception thrown from LifecycleProcessor on context close", ex);}// Destroy all cached singletons in the context's BeanFactory.// 销毁beandestroyBeans();// Close the state of this context itself.closeBeanFactory();// Let subclasses do some final clean-up if they wish...onClose();this.active.set(false);}
}
destroyBeans()
方法
AbstractApplicationContext
类的 destroyBeans()
方法
protected void destroyBeans() {getBeanFactory().destroySingletons();
}
destroySingletons()
方法
DefaultListableBeanFactory
类中的 destroySingletons()
方法
@Override
public void destroySingletons() {super.destroySingletons();this.manualSingletonNames.clear();clearByTypeCache();
}
destroySingletons()
方法
DefaultSingletonBeanRegistry
类中的 destroySingletons()
方法
public void destroySingletons() {if (logger.isDebugEnabled()) {logger.debug("Destroying singletons in " + this);}synchronized (this.singletonObjects) {this.singletonsCurrentlyInDestruction = true;}String[] disposableBeanNames;synchronized (this.disposableBeans) {disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());}for (int i = disposableBeanNames.length - 1; i >= 0; i--) {// 方法调用如下destroySingleton(disposableBeanNames[i]);}this.containedBeanMap.clear();this.dependentBeanMap.clear();this.dependenciesForBeanMap.clear();synchronized (this.singletonObjects) {this.singletonObjects.clear();this.singletonFactories.clear();this.earlySingletonObjects.clear();this.registeredSingletons.clear();this.singletonsCurrentlyInDestruction = false;}
}public void destroySingleton(String beanName) {// Remove a registered singleton of the given name, if any.removeSingleton(beanName);// Destroy the corresponding DisposableBean instance.DisposableBean disposableBean;synchronized (this.disposableBeans) {disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);}// 方法调用如下destroyBean(beanName, disposableBean);
}protected void destroyBean(String beanName, DisposableBean bean) {// Trigger destruction of dependent beans first...Set<String> dependencies = this.dependentBeanMap.remove(beanName);if (dependencies != null) {if (logger.isDebugEnabled()) {logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);}for (String dependentBeanName : dependencies) {destroySingleton(dependentBeanName);}}// Actually destroy the bean now...if (bean != null) {try {// 调用 DisposableBeanAdapter 的 destroy()bean.destroy();}catch (Throwable ex) {logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);}}// Trigger destruction of contained beans...Set<String> containedBeans = this.containedBeanMap.remove(beanName);if (containedBeans != null) {for (String containedBeanName : containedBeans) {destroySingleton(containedBeanName);}}// Remove destroyed bean from other beans' dependencies.synchronized (this.dependentBeanMap) {for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {Map.Entry<String, Set<String>> entry = it.next();Set<String> dependenciesToClean = entry.getValue();dependenciesToClean.remove(beanName);if (dependenciesToClean.isEmpty()) {it.remove();}}}// Remove destroyed bean's prepared dependency information.this.dependenciesForBeanMap.remove(beanName);
}
流程总结为
- 取出需要执行销毁方法的
bean
(前面添加到了disposableBeans
中)
// DefaultSingletonBeanRegistry 的属性
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
- 遍历每个
bean
执行销毁方法 - 取出
bean
的依赖方,先销毁依赖方(就是之前bean
装配提到的@DependsOn
标志的依赖方) - 执行
bean
的destroy
销毁方法,包括下面4
项- 调用
DestructionAwareBeanPostProcessor
来执行销毁方法 - 执行
DisposableBean
的destroy
方法 - 执行
init-method
指定的destroy
方法 - 执行
@Bean
属性指定的destroy
方法
- 调用
- 销毁内部类对象
- 从依赖关系中去掉自己
destroy()
方法
DisposableBeanAdapter
的 destroy()
方法
public void destroy() {if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {// 调用DestructionAwareBeanPostProcessor来执行销毁方法,就是上文提到的for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {processor.postProcessBeforeDestruction(this.bean, this.beanName);}}if (this.invokeDisposableBean) {if (logger.isDebugEnabled()) {logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");}try {// 执行DisposableBean#destroy方法if (System.getSecurityManager() != null) {AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws Exception {((DisposableBean) bean).destroy();return null;}}, acc);}else {((DisposableBean) bean).destroy();}}catch (Throwable ex) {String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";if (logger.isDebugEnabled()) {logger.warn(msg, ex);}else {logger.warn(msg + ": " + ex);}}}// 执行destroy-method指定的销毁方法if (this.destroyMethod != null) {invokeCustomDestroyMethod(this.destroyMethod);}else if (this.destroyMethodName != null) {Method methodToCall = determineDestroyMethod();if (methodToCall != null) {invokeCustomDestroyMethod(methodToCall);}}
}
Spring源码之bean的销毁registerDisposableBeanIfNecessary方法解读相关推荐
- Spring源码解析-bean实例化
Spring源码解析-bean实例化 本文介绍Spring创建 bean 过程中的第一个步骤:实例化 bean. 1. Bean实例化源码 虽然实例化Bean有多种方式(包括静态工厂和工厂实例 ...
- Spring 源码解析 - Bean创建过程 以及 解决循环依赖
一.Spring Bean创建过程以及循环依赖 上篇文章对 Spring Bean资源的加载注册过程进行了源码梳理和解析,我们可以得到结论,资源文件中的 bean 定义信息,被组装成了 BeanDef ...
- Spring源码深度解析,Spring源码以及Bean的生命周期(五)(附代码示例:)
五)Bean 的生命周期,创建---初始化---销毁的过程 目录 五)Bean 的生命周期,创建---初始化---销毁的过程 一 , 指定初始化方法 init-method 方法 二 ,指定销毁 ...
- Spring源码剖析——Bean的配置与启动
IOC介绍 相信大多数人在学习Spring时 IOC 和 Bean 算得上是最常听到的两个名词,IOC在学习Spring当中出现频率如此之高必然有其原因.如果我们做一个比喻的话,把Bean说成Sp ...
- Spring源码之Bean的注册(使用XML配置的方式)
本文分析的Spring源码是5.2.2版本,使用Gradle进行管理. 一.Bean的注册,先来看通过XML配置Bean的方式 1.配置applicationContext.xml: <?xml ...
- 一、如何阅读Spring源码(全网最简单的方法)
学习Java最好最有效的方法是学习Spring,但是最笨最没效的方法也是学习Spring. 为什么这么说呢?道理其实很简单 A.Spring很庞大,很完善,也非常的底层,如果我们学会的Spring,那 ...
- Spring源码分析——Bean的生命周期
文章目录 说明 测试代码 说明 本文从源码的角度分析Spring中Bean的加载过程,本文使用的Spring版本为4.3.25.RELEASE 测试代码 测试代码如下,根据这段简单的测试代码,一步步跟 ...
- 三 spring源码解析--- Bean解析接口结构分析
2019独角兽企业重金招聘Python工程师标准>>> 解析Bean是通过定义抽象的bean reader来解析,结构图如下 1.AbstractBeanDefinitionRead ...
- Spring源码之Bean的注册(注解方式)
1.创建AnnotationConfigApplicationContext AnnotationConfigApplicationContext context = new AnnotationCo ...
- Spring源码学习--Bean的生命周期
Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的.我们通常使用ApplicationContext作为Spring ...
最新文章
- 深度学习如何挑选GPU?
- linux-----shell高级编程----sed应用
- java8中Predicate用法
- 【python opencv 计算机视觉零基础到实战】二、 opencv文件格式与摄像头读取
- 汇编语言-018(FLD 、FST、FSTP、FCHS、FABS 、浮点运算符、浮点比较 )
- 编译 linux 3,linux内核的编译(3)
- UVA - 133 ​​​​​​​The Dole Queue
- 使用getApplication()作为上下文的对话框抛出“无法添加窗口-令牌null不适用于应用程序”
- 【ACL2020放榜!】事件抽取、关系抽取、NER、Few-Shot 相关论文整理
- 锁 公平 非公平_推荐引擎也需要公平!
- 数据库系统概念第四章习题答案
- 淘宝爬登录、取个人资料、微博绑定、收货地址、支付宝绑定设置、安全设置等信息、购物车、收藏宝贝和店铺、个人积分、退款维权、我的足迹...
- ROS_Noetic使用handeye-calib进行机械臂手眼标定
- ios 渐变透明背景_PPT设计的总是太单调,不如换个背景试试,超精彩!
- MATLAB/Simulink当真,开环Buck、闭环Buck、双闭环Buck仿真;开环控制的半桥LLC谐振变换器,全桥LLC谐振变换器和电压闭环控制的半桥LLC
- STM32F407 FSMC驱动MT29F4G08A NAND FLASH源代码分享
- ffmpeg批量处理视频和音频合成
- excel查找出不来了_Excel查找值不唯一,一个VLOOKUP公式拖拉出多个结果啦
- Flink DataStream API(基础版)
- AR | 增强现实简述
热门文章
- 翻译: 3.2. 从零开始实现线性回归 深入神经网络 pytorch
- 极客大学架构师训练营 系统架构 一致性哈希 Consistent Hashing 第五次作业
- 算法:Reverse Linked List
- jupyter notebook添加虚拟环境
- 用tensorflow实现线性回归算法
- gis投影中未定义的地理转换_PhotoScan中经纬度转换为投影坐标快捷方法
- 验证服务器的通用性,通用VNFM部署的可行性分析与验证
- linux的abrt目录满了,linux:abrt-cli list
- 【机器学习系列】GMM第一讲:两个角度认识高斯混合模型
- 用Tensorflow基于Deep Q Learning DQN 玩Flappy Bird