前言
本系列前面講解了Spring的bean定義、bean實(shí)例化、bean初始化等生命周期。這些步驟使我們能夠了解bean從創(chuàng)建到準(zhǔn)備好使用所經(jīng)歷的過程。但是,除了這些步驟,bean的銷毀也是非常重要的一步。在本系列的最后,我們將深入探討bean的銷毀過程,包括在什么情況下會(huì)發(fā)生銷毀、銷毀的順序以及如何在bean銷毀之前執(zhí)行一些清理任務(wù)等。通過學(xué)習(xí)bean的銷毀過程,我們將更全面地了解Spring的bean生命周期。
在Spring中,有多種方式可以銷毀bean。其中一種方式是在應(yīng)用程序關(guān)閉時(shí)顯式地調(diào)用applicationContext.close()
方法來關(guān)閉容器。這個(gè)方法將會(huì)銷毀所有還沒有被銷毀的bean。
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
applicationContext.close();
實(shí)現(xiàn)DisposableBean接口
實(shí)現(xiàn)DisposableBean接口是一種銷毀bean的簡單方式。當(dāng)bean容器關(guān)閉時(shí),Spring會(huì)調(diào)用DisposableBean的destroy()方法來銷毀bean。以下是一些示例代碼:
import org.springframework.beans.factory.DisposableBean;
@Component
public class MyBean implements DisposableBean {
@Override
public void destroy() throws Exception {
// 在這里清理資源
}
}
使用@PreDestroy注解
使用@PreDestroy注解是另一種簡單的方式來銷毀bean。當(dāng)bean容器關(guān)閉時(shí),Spring會(huì)調(diào)用使用@PreDestroy注解的方法來銷毀bean。以下是一些示例代碼:
import javax.annotation.PreDestroy;
@Component
public class MyBean {
@PreDestroy
public void cleanUp() throws Exception {
// 在這里清理資源
}
}
registerDisposableBeanIfNecessary
registerDisposableBeanIfNecessary()
方法是一個(gè)非常重要的方法,它是在bean創(chuàng)建后進(jìn)行處理bean銷毀邏輯的前提。在Spring的AbstractBeanFactory
類中,該方法會(huì)檢查當(dāng)前bean是否實(shí)現(xiàn)了DisposableBean
接口或者@PreDestroy
注解,如果是的話,就會(huì)將該bean添加到一個(gè)DisposableBeanAdapter
對(duì)象中,該對(duì)象會(huì)在bean銷毀時(shí)被調(diào)用以執(zhí)行銷毀任務(wù)。這個(gè)過程是在bean銷毀之前執(zhí)行的,以確保正確關(guān)閉應(yīng)用程序。
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}
我大概講下這個(gè)方法requiresDestruction
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
bean, getBeanPostProcessorCache().destructionAware))));
}
- DisposableBeanAdapter.hasDestroyMethod:校驗(yàn)是否實(shí)現(xiàn)了DisposableBean或者AutoCloseable接口,如果沒有的話,再查看是否bean定義的destroyMethodName屬性是
(inferred)
,如果是的話,那么直接找這個(gè)類是否有close方法沒有的話再找shutdown方法 - DisposableBeanAdapter.hasApplicableProcessors:是否有@PreDestroy注解
DisposableBeanAdapter
DisposableBeanAdapter
對(duì)象是一個(gè)適配器,用于在銷毀bean時(shí)執(zhí)行必要的處理。它會(huì)將DisposableBean
接口或@PreDestroy
注解的方法轉(zhuǎn)換為一個(gè)回調(diào)方法,以便在bean銷毀時(shí)執(zhí)行。這種適配器模式允許非標(biāo)準(zhǔn)的bean銷毀方法與Spring框架協(xié)同工作。
在將DisposableBeanAdapter
對(duì)象添加到一個(gè)DisposableBeanRegistry
對(duì)象中時(shí),Spring會(huì)將該對(duì)象添加到一個(gè)bean銷毀的注冊表中。當(dāng)需要銷毀所有bean時(shí),Spring就會(huì)從該注冊表中獲取所有需要銷毀的bean,并按照正確的順序執(zhí)行銷毀任務(wù)。這樣就可以確保應(yīng)用程序的正確關(guān)閉。
destroySingleton
當(dāng)Spring程序關(guān)閉時(shí),會(huì)調(diào)用destroyBeans
方法,這里我們分析關(guān)鍵部分代碼:
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
// 先從單例池中移除掉
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
- removeSingleton:先從單例池中移除掉
- this.disposableBeans.remove:這里返回的是我們之前調(diào)用registerDisposableBeanIfNecessary方法添加進(jìn)去的DisposableBeanAdapter適配器
- destroyBean:直接銷毀bean,這里注意一個(gè)小點(diǎn)就是如果當(dāng)前bean被其他bean依賴了,那么先移除銷毀其他Bean,然后就是調(diào)用適配器的destroy方法
總結(jié)
非常感謝您對(duì) Spring 生命周期系列文章的關(guān)注和支持,我們在過去一個(gè)月中深入了解了 Spring 框架中 Bean 的生成、初始化、后置處理和銷毀等過程,對(duì)于理解 Spring 框架的原理和機(jī)制非常有幫助。我們總結(jié)一下Spring到底做了那些事情將bean從生成到銷毀的全過程:文章來源:http://www.zghlxwxcb.cn/news/detail-456276.html
- 項(xiàng)目啟動(dòng)時(shí),ClassPathBeanDefinitionScanner掃描得到所有BeanDefinition,由于ACM技術(shù)所以此時(shí)beanclass屬性為String類型的bean的名稱
- 獲取合并后的BeanDefinition
- beanClass開始真正的被加載替換原有String類型的bean的名稱
- 調(diào)用實(shí)例化前處理方法applyBeanPostProcessorsBeforeInstantiation
- 通過構(gòu)造方法創(chuàng)建Bean實(shí)例
- 后置處理合并后的BeanDefinition,調(diào)用postProcessMergedBeanDefinition(尋找注入點(diǎn))
- 調(diào)用實(shí)例化后處理方法postProcessAfterInstantiation
- 開始進(jìn)行屬性注入:postProcessProperties
- 調(diào)用初始化前處理方法:applyBeanPostProcessorsBeforeInitialization
- 進(jìn)行初始化:invokeInitMethods,會(huì)調(diào)用指定init方法或者afterPropertiesSet方法
- 調(diào)用初始化后處理方法:applyBeanPostProcessorsAfterInitialization(AOP)
- 容器關(guān)閉時(shí),走bean的銷毀邏輯,即今天所講
這里面有很多邏輯流程我都在單獨(dú)的文章中有細(xì)講,比如FactoryBean、PropertyValues等等,由于是總結(jié)所以就不全寫出來了,也希望大家可以好好理解Spring源碼,下一步,我們將會(huì)著重講解 Bean 的屬性依賴注入。文章來源地址http://www.zghlxwxcb.cn/news/detail-456276.html
到了這里,關(guān)于Spring源碼:Bean生命周期(終章)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!