主要包含:
1.bean销毁前IOC容器的处理
2.bean销毁阶段的回调
public void stop() {
getLifecycleProcessor().stop();
publishEvent(new ContextStoppedEvent(this));
}
LifecycleProcessor处理器的stop方法也是先给所有Lifecycle bean分组,排序,依次调用stop方法。
ApplicationContext#closepublic void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
// catch ......
}
}
}
核心方法doClose()。
doCloseprotected void doClose() {
// Check whether an actual close attempt is necessary...
if (this.active.get() && this.closed.compareAndSet(false, true)) {
// logger ......
LiveBeansView.unregisterApplicationContext(this);
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
} // catch ......
// ......
核心逻辑:广播ContextClosedEvent 事件。
LifecycleProcessor#onClose // ......
// Stop all Lifecycle beans, to avoid delays during individual destruction.
if (this.lifecycleProcessor != null) {
try {
this.lifecycleProcessor.onClose();
} // catch ......
}
// ......
public void onClose() {
stopBeans();
this.running = false;
}
destroyBeans - 销毁bean
// ......
// Destroy all cached singletons in the context's BeanFactory.
destroyBeans();
// ......
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
获取到 ApplicationContext 内部的 BeanFactory ,让它去销毁所有的单实例 bean 。
DefaultListableBeanFactory#destroySingletons//DefaultListableBeanFactory#destroySingletons
public void destroySingletons() {
super.destroySingletons();
// 清空单实例bean的名称
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache();
}
private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
private final Map, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
private void clearByTypeCache() {
this.allBeanNamesByType.clear();
this.singletonBeanNamesByType.clear();
}
1.首先调用父类DefaultSingletonBeanRegistry 的destroySingletons 方法。
2.随后会清空所有的单实例 bean 的名称,以及 “类型到 name ” 的映射。( allBeanNamesByType 中保存了 bean 的类型包含的所有 bean ,如 Person 类型的 bean 在 IOC 容器中包含 master 和 admin )
//DefaultSingletonBeanRegistry#destroySingletons
public void destroySingletons() {
// logger ......
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
// set -> array
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
// 销毁所有单实例bean
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
// 清空一切缓存
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
核心:逐个销毁单实例bean。
destroySingleton单个bean的销毁流程:
public void destroySingleton(String beanName) {
super.destroySingleton(beanName);
removeManualSingletonName(beanName);
clearByTypeCache();
}
还是调用DefaultSingletonBeanRegistry 中的destroySingleton:
//DefaultSingletonBeanRegistry#destroySingleton
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
// 此处会清理掉BeanFactory中设计的用于处理bean循环依赖的三级缓存
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
核心:
1.清空BeanFactory中用于处理循环依赖的缓存。
2.回调bean的销毁动作。
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
Set dependencies;
synchronized (this.dependentBeanMap) {
dependencies = this.dependentBeanMap.remove(beanName);
}
if (dependencies != null) {
// logger ......
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName);
}
}
// ......
在销毁一个 bean 时,如果它有依赖其它的 bean ,则首要目标不是销毁自己,而是先销毁那些依赖的 bean ,所以这里会有递归调用上面 destroySingleton 方法的动作。
自定义bean销毁方法的回调 // ......
// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy();
}
// catch ......
}
// ......
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
// 回调DestructionAwareBeanPostProcessor
// 此处会有执行@PreDestroy注解标注的销毁方法
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
// logger ......
try {
// ......
else {
// 回调DisposableBean接口的destroy方法
((DisposableBean) this.bean).destroy();
}
}
// catch ......
}
// 回调自定义的destroy-method方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
bean 的销毁阶段生命周期回调的顺序:@PreDestroy → DisposableBean → destroy-method 。
处理bean中bean// ......
// Trigger destruction of contained beans...
Set 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);
}
}
// ......
例如:
这种嵌套 bean ,就会记录在 DefaultSingletonBeanRegistry 的 containedBeanMap 中,既然外头的 bean 要销毁了,那里头的这些 bean 也就应该被销毁了,所以这里又是取到那些内部构造好的 bean ,依次递归调用 destroySingleton 方法来销毁这些 bean 。
销毁被依赖的bean // ......
// Remove destroyed bean from other beans' dependencies.
synchronized (this.dependentBeanMap) {
for (Iterator>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry> entry = it.next();
Set dependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
// Remove destroyed bean's prepared dependency information.
this.dependenciesForBeanMap.remove(beanName);
}
当自己销毁之后,那些依赖了当前 bean 的 bean 也就应该被销毁。套路都是一样的,取到那些被依赖的 bean 的名称,依次递归调用 destroySingleton 方法销毁。
关闭BeanFactory// Close the state of this context itself. closeBeanFactory();
说是关闭 BeanFactory ,实际上更接近于 “销毁” ,因为原来的 BeanFactory 无论如何都无法继续用了。
在基于 xml 和基于注解驱动的两种 ApplicationContext 的实现里,它们的策略既相似又不同:
// AbstractRefreshableApplicationContext
protected final void closeBeanFactory() {
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory != null) {
beanFactory.setSerializationId(null);
this.beanFactory = null;
}
}
在基于 xml 配置文件的 ApplicationContext 中,它会获取到原有的 BeanFactory ,移除序列化 ID ,并直接丢弃原来的 BeanFactory 。
// GenericApplicationContext
protected final void closeBeanFactory() {
this.beanFactory.setSerializationId(null);
}
在基于注解驱动的 ApplicationContext 中,它只会给内部组合的 BeanFactory 移除序列化 ID 而已。
GenericApplicationContext不允许被重复刷新的原因rivate final AtomicBoolean refreshed = new AtomicBoolean();
protected final void refreshBeanFactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(false, true)) {
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
}
如果当前 GenericApplicationContext 是刚创建的,那么 refreshed 的值一定是 false ,此时使用 CAS 设置 true 是成功的,下面的 throw ex 动作不会执行;而第二次再调用 refresh 刷新 ApplicationContext 时,进入到该方法时,CAS 不通过,无法刷新 BeanFactory ,最终抛出异常。
剩余动作 // ......
// Let subclasses do some final clean-up if they wish...
// 给子类用的,然而子类没一个重写的
onClose();
// Reset local application listeners to pre-refresh state.
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Switch to inactive.
this.active.set(false);
}
总结:
bean 对象在销毁时,由 ApplicationContext 发起关闭动作。销毁 bean 的阶段,由 BeanFactory 取出所有单实例 bean ,并逐个销毁。
销毁动作会先将当前 bean 依赖的所有 bean 都销毁,随后回调自定义的 bean 的销毁方法,之后如果 bean 中有定义内部 bean 则会一并销毁,最后销毁那些依赖了当前 bean 的 bean 也一起销毁。



