接上文SpringBoot关闭时都做了哪些事?,本文我们详细分析一下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);
。
【1】核心方法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
【2】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