SpringBoot关闭过程中销毁DisposableBean解读

 更新时间:2023年12月05日 11:25:54   作者:流烟默  
这篇文章主要介绍了SpringBoot关闭过程中销毁DisposableBean解读,一个bean的生命周期,指的是 bean 从创建,初始化,一系列使用,销毁的过程,今天来讲讲 bean 的初始化和销毁的方法,需要的朋友可以参考下

DisposableBean的destroy过程

DefaultSingletonBeanRegistry的destroySingleton方法。

public void destroySingleton(String beanName) {
	// Remove a registered singleton of the given name, if any.
	// 从缓存中移除当前beanName
	removeSingleton(beanName);
	// Destroy the corresponding DisposableBean instance.
	// 从disposableBeans集合中移除当前 beanName
	DisposableBean disposableBean;
	synchronized (this.disposableBeans) {
		disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
	}
	// 这是核心方法
	destroyBean(beanName, disposableBean);
}

disposableBeans里面存放的是beanName以及对应的DisposableBeanAdapter实例。其他方法我们过一下即可,这里我们着重分析destroyBean(beanName, disposableBean);。

核心方法DefaultSingletonBeanRegistry的destroyBean

// DefaultSingletonBeanRegistry
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
	// Trigger destruction of dependent beans first...
	Set<String> dependencies;
	//dependentBeanMap存放的是哪些bean依赖于key
	synchronized (this.dependentBeanMap) {
		// Within full synchronization in order to guarantee a disconnected Set
		dependencies = this.dependentBeanMap.remove(beanName);
	}
	// 首先触发那些依赖于当前beanName的bean的销毁流程
	if (dependencies != null) {
		if (logger.isTraceEnabled()) {
			logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
		}
		for (String dependentBeanName : dependencies) {
			destroySingleton(dependentBeanName);
		}
	}
	// Actually destroy the bean now...
	// bean销毁的过程入口,触发DisposableBeanAdapter的destroy方法
	if (bean != null) {
		try {
			bean.destroy();
		}
		catch (Throwable ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
			}
		}
	}
	// Trigger destruction of contained beans...
	// 获取当前beanName对应的containedBeans,如果有,则遍历触发销毁流程
	Set<String> containedBeans;
	synchronized (this.containedBeanMap) {
		// Within full synchronization in order to guarantee a disconnected Set
		containedBeans = this.containedBeanMap.remove(beanName);
	}
	if (containedBeans != null) {
		for (String containedBeanName : containedBeans) {
			destroySingleton(containedBeanName);
		}
	}
	// Remove destroyed bean from other beans' dependencies.
	// 遍历dependentBeanMap的value,移除掉当前beanName。
	//之后如果value为空,其从dependentBeanMap移除掉当前entry
	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.
	// 从 dependenciesForBeanMap中移除当前beanName对应的entry
	this.dependenciesForBeanMap.remove(beanName);
}

方法逻辑梳理如下:

  • 首先触发那些依赖于当前beanName的bean的销毁流程
  • bean.destroy();触发DisposableBeanAdapter的destroy方法
  • 获取当前实例维护的DestructionAwareBeanPostProcessor 触发其postProcessBeforeDestruction方法,如果有@PreDestroy注解的方法,这时会被触发。
  • 根据invokeDisposableBean判断是否触发destroy方法
  • 尝试触发其自定义destroy method
  • 获取当前beanName对应的containedBeans,如果有,则遍历触发销毁流程
  • 遍历dependentBeanMap的value,移除掉当前beanName。之后如果value为空,其从dependentBeanMap移除掉当前entry
  • 从 dependenciesForBeanMap中移除当前beanName对应的entry

DisposableBeanAdapter

上面提到了bean.destroy();触发DisposableBeanAdapter的destroy方法,方法如下所示:

@Override
public void destroy() {
//获取当前实例维护的DestructionAwareBeanPostProcessor 触发其postProcessBeforeDestruction方法
	if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
		for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
			processor.postProcessBeforeDestruction(this.bean, this.beanName);
		}
	}
// 是否触发destroy方法
	if (this.invokeDisposableBean) {
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
		}
		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((DisposableBean) this.bean).destroy();
					return null;
				}, this.acc);
			}
			else {
				((DisposableBean) this.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);
			}
		}
	}
// 如果destroyMethod 不为null,则触发自定义销毁方法
	if (this.destroyMethod != null) {
		invokeCustomDestroyMethod(this.destroyMethod);
	}
	else if (this.destroyMethodName != null) {
	// 如果destroyMethodName 不为null,则获取并触发自定义销毁方法
		Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
		if (methodToInvoke != null) {
			invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
		}
	}
}

方法流程

获取当前实例维护的DestructionAwareBeanPostProcessor 触发其postProcessBeforeDestruction方法,如果有@PreDestroy注解的方法,这时会被触发。

根据invokeDisposableBean判断是否触发destroy方法

尝试触发其自定义destroy method

到此这篇关于SpringBoot关闭过程中销毁DisposableBean解读的文章就介绍到这了,更多相关SpringBoot销毁DisposableBean内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Springboot配置Swagger的实现示例

    Springboot配置Swagger的实现示例

    Swagger 是一种提高 API 开发和维护效率的工具,它使开发者能够更轻松地构建、测试和文档化 API,本文主要介绍了Springboot配置Swagger的实现示例,感兴趣的可以了解一下
    2023-10-10
  • Java过滤器Filter的基本使用教程

    Java过滤器Filter的基本使用教程

    过滤器通常对一些web资源进行拦截,做完一些处理器再交给下一个过滤器处理,直到所有的过滤器处理器,再调用servlet实例的service方法进行处理。本文将通过示例为大家讲解Java中过滤器Filter的用法与实现,需要的可以参考一下
    2023-02-02
  • java 文件和byte互转的实例

    java 文件和byte互转的实例

    下面小编就为大家分享一篇java 文件和byte互转的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • IDEA报错:Unable to save settings Failed to save settings

    IDEA报错:Unable to save settings Failed to save settings

    这篇文章主要介绍了IDEA报错:Unable to save settings Failed to save settings的相关知识,本文给大家分享问题原因及解决方案,需要的朋友可以参考下
    2020-09-09
  • Java BufferedOutputStream类的常用方法讲解

    Java BufferedOutputStream类的常用方法讲解

    这篇文章主要介绍了Java BufferedOutputStream类的常用方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • SpringBoot Schedule调度任务的动态管理

    SpringBoot Schedule调度任务的动态管理

    Scheduled定时任务是Spring boot自身提供的功能,所以不需要引入Maven依赖包,下面这篇文章主要给大家介绍了关于SpringBoot通过@Scheduled实现定时任务以及问题解决的相关资料,需要的朋友可以参考下
    2023-02-02
  • Spring Boot整合SSE实时通信的问题小结

    Spring Boot整合SSE实时通信的问题小结

    本文介绍了服务器发送事件(Server-Sent Events,SSE)技术,其主要特点包括单向数据流、自动重连、自定义事件类型等,SSE适用于实时更新场景,如新闻推送、评论系统等,感兴趣的朋友跟随小编一起看看吧
    2025-01-01
  • 利用java实现一个客户信息管理系统

    利用java实现一个客户信息管理系统

    这篇文章主要给大家介绍了关于利用java实现一个客户信息管理系统的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java.lang.NullPointerException的错误解决

    Java.lang.NullPointerException的错误解决

    Java中NullPointerException是一种常见的运行时异常,通常发生在尝试调用null对象的方法或访问其属性时,具有一定的参考价值,感兴趣的可以了解一下
    2024-09-09
  • Java中的synchronized关键字

    Java中的synchronized关键字

    这篇文章主要介绍了Java中的synchronized关键字,synchronized可以保证方法或代码块在运行时,同一时刻只有一个线程可以进入到临界区(互斥性),同时它还保证了共享变量的内存可见性,下面我们就来看看你文章对synchronized锁的介绍,需要的朋友也可以参考一下
    2021-12-12

最新评论