接上文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