容器在 refresh 中发生异常,都会处理 destroyBeans
、cancelRefresh
两个动作,代码如下:
// AbstractApplicationContext#refresh()catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// <1> 销毁已经创建的Bean// Destroy already created singletons to avoid dangling resources.destroyBeans();// <2> 重置容器激活标签// Reset 'active' flag.cancelRefresh(ex);// 抛出异常// Propagate exception to caller.throw ex;}
说明:
通常都是DefaultListableBeanFactory#destroySingletons()
方法,销毁单例对象,然后清理 BeanFactory 的一些注册缓存,直接上代码:
// DefaultListableBeanFactory@Overridepublic void destroySingletons() {// <1> 优先调用 DefaultSingletonBeanRegistry 里面的 destroySingletons() 方法super.destroySingletons();// <2> 更新手册单例,这里采用了 Consumer、Predicate 两个 1.8 的特性// 清理的是 manualSingletonNames,这是一个按注册顺序的缓存updateManualSingletonNames(Set::clear, set -> !set.isEmpty());// <3> 根据类型清除clearByTypeCache();}
说明:
终于:核心内容在 <1>
调用的是父类 DefaultSingletonBeanRegistry
来进行对单例对象,进行销毁动作,代码如下:
// DefaultSingletonBeanRegistrypublic void destroySingletons() {if (logger.isTraceEnabled()) {logger.trace("Destroying singletons in " + this);}// <1> 设置 Destruction 销毁标识为 true,代表销毁中synchronized (this.singletonObjects) {this.singletonsCurrentlyInDestruction = true;}// <2> disposableBeanNames 是已经销毁的 bean 名称String[] disposableBeanNames;synchronized (this.disposableBeans) {disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());}// <3> 循环销毁 beanfor (int i = disposableBeanNames.length - 1; i >= 0; i--) {destroySingleton(disposableBeanNames[i]);}// <4> 清除,BeanFactory 缓存this.containedBeanMap.clear();this.dependentBeanMap.clear();this.dependenciesForBeanMap.clear();// <5> 清除,单例的缓存,这里是clear 清除所有的,上面是 remove 删除单个clearSingletonCache();}
说明:
重点:<3>
,我们接下来分析
public void destroySingleton(String beanName) {// <1> 删除 singleton,删除的是单例 三级缓存// Remove a registered singleton of the given name, if any.removeSingleton(beanName);// <2> 销毁相应的DisposableBean实例。// Destroy the corresponding DisposableBean instance.DisposableBean disposableBean;synchronized (this.disposableBeans) {disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);}// <3> 去销毁 bean 实例destroyBean(beanName, disposableBean);}
说明:
重点是:<3>
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {// tips:// bean的销毁逻辑,优先销毁bean的依赖,然后销毁bean// <1> 首先从 bean 的依赖开始销毁// Trigger destruction of dependent beans first...Set<String> dependencies;synchronized (this.dependentBeanMap) {// <2> 将谁依赖他,从map中删除// 完全同步,命令保证断开设置// Within full synchronization in order to guarantee a disconnected Setdependencies = this.dependentBeanMap.remove(beanName);}// <3> 有其他class 依赖这个 class 进入if (dependencies != null) {if (logger.isTraceEnabled()) {logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);}// <4> 这里是个递归调用,会再次进入到这里for (String dependentBeanName : dependencies) {destroySingleton(dependentBeanName);}}// <5> 销毁实现 DisposableBean 的 bean 实例// Actually destroy the bean now...if (bean != null) {try {// <6> 调用bean的 destroy() 方法bean.destroy();} catch (Throwable ex) {if (logger.isWarnEnabled()) {logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);}}}// <6> 销毁容器里面的 bean,// containedBeans 是移除 beanName 后其他的依赖,这里使用一个递归继续销毁// Trigger destruction of contained beans...Set<String> containedBeans;// <7> 销毁容器的 bean,从 containedBeanMap 移除,synchronized (this.containedBeanMap) {// Within full synchronization in order to guarantee a disconnected Set// 这里的map关系是:bean名称之间依赖,bean name设置bean包含的bean名称。containedBeans = this.containedBeanMap.remove(beanName);}// <8> 对移除后的,依赖进行销毁动作。if (containedBeans != null) {for (String containedBeanName : containedBeans) {destroySingleton(containedBeanName);}}// <9> 从其他bean的依赖项中删除销毁的bean。// Remove destroyed bean from other beans' dependencies.synchronized (this.dependentBeanMap) {// <9> 迭代 dependentBeanMap 这个map,从 value 中移除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);// 如果 dependenciesToClean 为空了,就把这个 key 直接删除了if (dependenciesToClean.isEmpty()) {it.remove();}}}// <10> 删除他依赖谁,的map缓存。// Remove destroyed bean's prepared dependency information.this.dependenciesForBeanMap.remove(beanName);}
说明:
到这整个 destroy() 动作已经完了。
关闭刷新,里面比较简单,代码如下:
// AbstractRefreshableApplicationContext@Overrideprotected void cancelRefresh(BeansException ex) {// <1> 清除 BeanFactory 的 SerializationIdsynchronized (this.beanFactoryMonitor) {if (this.beanFactory != null) {this.beanFactory.setSerializationId(null);}}// <2> 调用父类的 cancelRefresh 将容器刷新状态设置成 falsesuper.cancelRefresh(ex);}// AbstractApplicationContextprotected void cancelRefresh(BeansException ex) {// <1> 将容器刷新状态设置成 falsethis.active.set(false);}
说明:
ps:完结~