阅读须知
- Spring源码版本:4.3.8
- 文章中使用/* */注释的方法会做深入分析
正文
我们来看几个销毁bean的场景,在一些异常情况,例如Spring上下文初始化失败时,会销毁已经创建的单例bean,这时会调用相关销毁方法,在Spring容器关闭时,同样会调用disposableBeans的销毁方法:
AbstractApplicationContext:
public void registerShutdownHook() {
if (this.shutdownHook == null) {
this.shutdownHook = new Thread() {
@Override
public void run() {
synchronized (startupShutdownMonitor) {
/* 关闭容器 */
doClose();
}
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
AbstractApplicationContext:
public void close() {
synchronized (this.startupShutdownMonitor) {
/* 关闭容器 */
doClose();
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
}
}
}
}
在容器注册的关闭钩子的关闭方法中都调用了doClose方法,我们来分析这个方法:
protected void doClose() {
// 判断active激活标记(在初始化上下文时被设置为true用于标记激活状态)并且将closed标记设置为true
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) {
logger.info("Closing " + this);
}
// 卸载注册的JMX的MBean
LiveBeansView.unregisterApplicationContext(this);
try {
// 发布容器关闭事件
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
}
try {
// 调用实现了Lifecycle的bean的stop方法,关于Lifecycle,我们在标签解析的文章中分析过
getLifecycleProcessor().onClose();
}
catch (Throwable ex) {
logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
}
/* 销毁bean */
destroyBeans();
// 关闭BeanFactory,将BeanFactory序列化id和本身置为null
closeBeanFactory();
// 子类扩展
onClose();
// 将激活标记置为false
this.active.set(false);
}
}
AbstractApplicationContext:
protected void destroyBeans() {
// 销毁单例bean
getBeanFactory().destroySingletons();
}
DefaultListableBeanFactory:
public void destroySingletons() {
/* 调用父类的销毁方法销毁单例bean */
super.destroySingletons();
// 清空手工注册的beanName的缓存
this.manualSingletonNames.clear();
// 清空类型-->beanName的映射缓存
clearByTypeCache();
}
DefaultSingletonBeanRegistry:
public void destroySingletons() {
if (logger.isDebugEnabled()) {
logger.debug("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
// 设置正在销毁的标记为true
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
/* 遍历销毁之前注册的所有disposableBean */
destroySingleton(disposableBeanNames[i]);
}
// 清空beanName --> 它包含的所有内部beanName集合的映射缓存
this.containedBeanMap.clear();
// 清空beanName --> 它依赖的所有beanName集合的映射缓存
this.dependentBeanMap.clear();
// 清空beanName --> 依赖它的所有beanName集合的映射缓存
this.dependenciesForBeanMap.clear();
synchronized (this.singletonObjects) {
// 清空单例bean缓存
this.singletonObjects.clear();
// 清空单例工厂缓存
this.singletonFactories.clear();
// 清空提前暴露的beanName --> bean的映射缓存
this.earlySingletonObjects.clear();
// 清空已经注册的单例bean缓存
this.registeredSingletons.clear();
// 设置正在销毁的标记为false
this.singletonsCurrentlyInDestruction = false;
}
}
DefaultSingletonBeanRegistry:
public void destroySingleton(String beanName) {
// 清除bean的相应缓存
removeSingleton(beanName);
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
// 移除并获取disposableBean
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
/* 销毁 */
destroyBean(beanName, disposableBean);
}
DefaultSingletonBeanRegistry:
protected void destroyBean(String beanName, DisposableBean bean) {
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) {
// 首选递归销毁所有当前bean依赖的bean
destroySingleton(dependentBeanName);
}
}
if (bean != null) {
try {
// 调用destory方法
bean.destroy();
}
catch (Throwable ex) {
logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
}
}
Set<String> containedBeans = this.containedBeanMap.remove(beanName);
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
// 递归销毁当前bean包含的所有内部bean
destroySingleton(containedBeanName);
}
}
synchronized (this.dependentBeanMap) {
// 遍历找出所有依赖当前bean的列表,将当前bean从被依赖的列表中移除
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();
}
}
}
// 从所有依赖当前bean的映射中移除依赖关系
this.dependenciesForBeanMap.remove(beanName);
}
整个Spring销毁bean的流程到这里就结束了。