SpringBoot關閉過程中銷毀DisposableBean解讀
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);。
核心方法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);
}
// 首先觸發(fā)那些依賴于當前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銷毀的過程入口,觸發(fā)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,如果有,則遍歷觸發(fā)銷毀流程
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);
}方法邏輯梳理如下:
- 首先觸發(fā)那些依賴于當前beanName的bean的銷毀流程
- bean.destroy();觸發(fā)DisposableBeanAdapter的destroy方法
- 獲取當前實例維護的DestructionAwareBeanPostProcessor 觸發(fā)其postProcessBeforeDestruction方法,如果有@PreDestroy注解的方法,這時會被觸發(fā)。
- 根據(jù)invokeDisposableBean判斷是否觸發(fā)destroy方法
- 嘗試觸發(fā)其自定義destroy method
- 獲取當前beanName對應的containedBeans,如果有,則遍歷觸發(fā)銷毀流程
- 遍歷dependentBeanMap的value,移除掉當前beanName。之后如果value為空,其從dependentBeanMap移除掉當前entry
- 從 dependenciesForBeanMap中移除當前beanName對應的entry
DisposableBeanAdapter
上面提到了bean.destroy();觸發(fā)DisposableBeanAdapter的destroy方法,方法如下所示:
@Override
public void destroy() {
//獲取當前實例維護的DestructionAwareBeanPostProcessor 觸發(fā)其postProcessBeforeDestruction方法
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
// 是否觸發(fā)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,則觸發(fā)自定義銷毀方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
// 如果destroyMethodName 不為null,則獲取并觸發(fā)自定義銷毀方法
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}方法流程
獲取當前實例維護的DestructionAwareBeanPostProcessor 觸發(fā)其postProcessBeforeDestruction方法,如果有@PreDestroy注解的方法,這時會被觸發(fā)。
根據(jù)invokeDisposableBean判斷是否觸發(fā)destroy方法
嘗試觸發(fā)其自定義destroy method
到此這篇關于SpringBoot關閉過程中銷毀DisposableBean解讀的文章就介紹到這了,更多相關SpringBoot銷毀DisposableBean內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java Servlet線程中AsyncContext異步處理Http請求
這篇文章主要介紹了Java Servlet線程中AsyncContext異步處理Http請求及在業(yè)務中應用,AsyncContext是Servlet 3.0使Servlet 線程不再需要一直阻塞,直到業(yè)務處理完畢才能再輸出響應,最后才結束該Servlet線程2023-03-03
MyBatis?和?MyBatis-Plus從語法詳解和優(yōu)劣對比
MyBatis和MyBatis-Plus是Java生態(tài)中常用的持久層框架,其中?MyBatis-Plus是在?MyBatis?基礎上的增強工具,下面從語法詳解和優(yōu)劣對比兩部分展開說明,感興趣的朋友一起看看吧2025-07-07
SpringCloud Alibaba使用Seata處理分布式事務的技巧
在傳統(tǒng)的單體項目中,我們使用@Transactional注解就能實現(xiàn)基本的ACID事務了,隨著微服務架構的引入,需要對數(shù)據(jù)庫進行分庫分表,每個服務擁有自己的數(shù)據(jù)庫,這樣傳統(tǒng)的事務就不起作用了,那么我們如何保證多個服務中數(shù)據(jù)的一致性呢?跟隨小編一起通過本文了解下吧2021-06-06

