SpringBoot關(guān)閉過(guò)程中銷(xiāo)毀DisposableBean解讀
DisposableBean的destroy過(guò)程
DefaultSingletonBeanRegistry的destroySingleton方法。
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
// 從緩存中移除當(dāng)前beanName
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
// 從disposableBeans集合中移除當(dāng)前 beanName
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
// 這是核心方法
destroyBean(beanName, disposableBean);
}disposableBeans里面存放的是beanName以及對(duì)應(yīng)的DisposableBeanAdapter實(shí)例。其他方法我們過(guò)一下即可,這里我們著重分析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依賴(lài)于key
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
// 首先觸發(fā)那些依賴(lài)于當(dāng)前beanName的bean的銷(xiāo)毀流程
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銷(xiāo)毀的過(guò)程入口,觸發(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...
// 獲取當(dāng)前beanName對(duì)應(yīng)的containedBeans,如果有,則遍歷觸發(fā)銷(xiāo)毀流程
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,移除掉當(dāng)前beanName。
//之后如果value為空,其從dependentBeanMap移除掉當(dāng)前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中移除當(dāng)前beanName對(duì)應(yīng)的entry
this.dependenciesForBeanMap.remove(beanName);
}方法邏輯梳理如下:
- 首先觸發(fā)那些依賴(lài)于當(dāng)前beanName的bean的銷(xiāo)毀流程
- bean.destroy();觸發(fā)DisposableBeanAdapter的destroy方法
- 獲取當(dāng)前實(shí)例維護(hù)的DestructionAwareBeanPostProcessor 觸發(fā)其postProcessBeforeDestruction方法,如果有@PreDestroy注解的方法,這時(shí)會(huì)被觸發(fā)。
- 根據(jù)invokeDisposableBean判斷是否觸發(fā)destroy方法
- 嘗試觸發(fā)其自定義destroy method
- 獲取當(dāng)前beanName對(duì)應(yīng)的containedBeans,如果有,則遍歷觸發(fā)銷(xiāo)毀流程
- 遍歷dependentBeanMap的value,移除掉當(dāng)前beanName。之后如果value為空,其從dependentBeanMap移除掉當(dāng)前entry
- 從 dependenciesForBeanMap中移除當(dāng)前beanName對(duì)應(yīng)的entry
DisposableBeanAdapter
上面提到了bean.destroy();觸發(fā)DisposableBeanAdapter的destroy方法,方法如下所示:
@Override
public void destroy() {
//獲取當(dāng)前實(shí)例維護(hù)的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ā)自定義銷(xiāo)毀方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
// 如果destroyMethodName 不為null,則獲取并觸發(fā)自定義銷(xiāo)毀方法
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}方法流程
獲取當(dāng)前實(shí)例維護(hù)的DestructionAwareBeanPostProcessor 觸發(fā)其postProcessBeforeDestruction方法,如果有@PreDestroy注解的方法,這時(shí)會(huì)被觸發(fā)。
根據(jù)invokeDisposableBean判斷是否觸發(fā)destroy方法
嘗試觸發(fā)其自定義destroy method
到此這篇關(guān)于SpringBoot關(guān)閉過(guò)程中銷(xiāo)毀DisposableBean解讀的文章就介紹到這了,更多相關(guān)SpringBoot銷(xiāo)毀DisposableBean內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot配置Swagger的實(shí)現(xiàn)示例
Swagger 是一種提高 API 開(kāi)發(fā)和維護(hù)效率的工具,它使開(kāi)發(fā)者能夠更輕松地構(gòu)建、測(cè)試和文檔化 API,本文主要介紹了Springboot配置Swagger的實(shí)現(xiàn)示例,感興趣的可以了解一下2023-10-10
IDEA報(bào)錯(cuò):Unable to save settings Failed to save settings
這篇文章主要介紹了IDEA報(bào)錯(cuò):Unable to save settings Failed to save settings的相關(guān)知識(shí),本文給大家分享問(wèn)題原因及解決方案,需要的朋友可以參考下2020-09-09
Java BufferedOutputStream類(lèi)的常用方法講解
這篇文章主要介紹了Java BufferedOutputStream類(lèi)的常用方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
SpringBoot?Schedule調(diào)度任務(wù)的動(dòng)態(tài)管理
Scheduled定時(shí)任務(wù)是Spring?boot自身提供的功能,所以不需要引入Maven依賴(lài)包,下面這篇文章主要給大家介紹了關(guān)于SpringBoot通過(guò)@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)以及問(wèn)題解決的相關(guān)資料,需要的朋友可以參考下2023-02-02
Spring Boot整合SSE實(shí)時(shí)通信的問(wèn)題小結(jié)
本文介紹了服務(wù)器發(fā)送事件(Server-Sent Events,SSE)技術(shù),其主要特點(diǎn)包括單向數(shù)據(jù)流、自動(dòng)重連、自定義事件類(lèi)型等,SSE適用于實(shí)時(shí)更新場(chǎng)景,如新聞推送、評(píng)論系統(tǒng)等,感興趣的朋友跟隨小編一起看看吧2025-01-01
利用java實(shí)現(xiàn)一個(gè)客戶(hù)信息管理系統(tǒng)
這篇文章主要給大家介紹了關(guān)于利用java實(shí)現(xiàn)一個(gè)客戶(hù)信息管理系統(tǒng)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Java.lang.NullPointerException的錯(cuò)誤解決
Java中NullPointerException是一種常見(jiàn)的運(yùn)行時(shí)異常,通常發(fā)生在嘗試調(diào)用null對(duì)象的方法或訪(fǎng)問(wèn)其屬性時(shí),具有一定的參考價(jià)值,感興趣的可以了解一下2024-09-09

