這篇文章是我在系統(tǒng)學(xué)習(xí)Spring源碼之后,基于自己對Spring源碼的理解,來詳細(xì)分析Spring之Bean的銷毀過程。
成都創(chuàng)新互聯(lián)主營吉縣網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,成都App定制開發(fā),吉縣h5小程序開發(fā)搭建,吉縣網(wǎng)站營銷推廣歡迎吉縣等地區(qū)企業(yè)咨詢
目錄
前言
一、注冊有銷毀邏輯的Bean
1.判斷當(dāng)前Bean是否需要銷毀
1.1. 判斷當(dāng)前Bean是否有銷毀方法
1.2.?判斷有沒有DestructionAwareBeanPostProcessor,并且DestructionAwareBeanPostProcessor.requiresDestruction()方法返回true
2.注冊DisposableBean
二、Bean銷毀過程
1.容器關(guān)閉
2.執(zhí)行doClose()
在Bean創(chuàng)建的過程中,在最后(初始化之后),有一個步驟是去注冊DisposableBean,原型Bean是不會注冊成為DisposableBean的,因為Spring容器中是不會存原型Bean的,Spring是通過requiresDestruction()方法來判斷該Bean是否需要銷毀,對需要銷毀的Bean,封裝成DisposableBeanAdapter對象,最后調(diào)用registerDisposableBean()方法將DisposableBeanAdapter對象放入disposableBeans中,當(dāng)Spring容器關(guān)閉的時候,可以直接從該map中取出定義了銷毀邏輯的Bean,執(zhí)行它們銷毀的方法;
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
//requiresDestruction(bean, mbd),判斷當(dāng)前bean在銷毀的時候是否要執(zhí)行某些邏輯
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));
}
}
}
一、注冊有銷毀邏輯的Bean
1.判斷當(dāng)前Bean是否需要銷毀protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
//判斷當(dāng)前bean在銷毀時候,有沒有定義有關(guān)銷毀的某些方法,不是所有的bean在銷毀的時候都要去執(zhí)行有關(guān)銷毀的邏輯
return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
bean, getBeanPostProcessorCache().destructionAware))));
}
1.1. 判斷當(dāng)前Bean是否有銷毀方法1) 如果當(dāng)前bean實現(xiàn)了DisposableBean或AutoCloseable接口,重寫接口中的destroy()和close()方法,這兩個方法都是銷毀方法;
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
}
private static String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
if (destroyMethodName == null) {
destroyMethodName = beanDefinition.getDestroyMethodName();
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
(destroyMethodName == null && bean instanceof AutoCloseable)) {
destroyMethodName = null;
if (!(bean instanceof DisposableBean)) {
try {
destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex) {
try {
destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex2) {
// no candidate destroy method found
}
}
}
}
beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : "");
}
return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
}
2)如果沒有實現(xiàn)這兩個接口,則判斷當(dāng)前Bean的RootBeanDefinition中是否設(shè)置了銷毀方法的名字,設(shè)置銷毀方法名有兩種場景:
場景一:自定義的方法名字,Spring會將此方法的名字作為銷毀方法的名字;
場景二:指定了特定的銷毀方法的名字:"(inferred)",則會將該Bean中close()和shutdown()作為銷毀方法(前提是Bean里面有這兩個方法);
@Component
public class MyMergedBeanDefinitionPostProcessor1 implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class>beanType, String beanName) {
if (beanName.equals("xxx")) {
//設(shè)置Spring指定的特定的名字"(inferred)"
beanDefinition.setDestroyMethodName("(inferred)");、
//自定義銷毀方法的名字
beanDefinition.setDestroyMethodName("customDestory");
}
}
}
初始化和銷毀方法名都是在創(chuàng)建Bean過程中的合并后的BeanDefination的后置處理階段設(shè)置的,即MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()中完成的。
1.2.?判斷有沒有DestructionAwareBeanPostProcessor,并且DestructionAwareBeanPostProcessor.requiresDestruction()方法返回true· DestructionAwareBeanPostProcessor接口主要用于Bean銷毀,其中的requiresDestruction()判斷Bean是否需要銷毀,postProcessBeforeDestruction()是實現(xiàn)具體的銷毀邏輯,而InitDestroyAnnotationBeanPostProcessor就是DestructionAwareBeanPostProcessor的一個具體實現(xiàn);
·?這里主要針對@PreDestroy注解,它主要用來定義銷毀方法(被該注解修飾的方法都是銷毀方法),該注解的處理就是在InitDestroyAnnotationBeanPostProcessor類中完成,它會緩存每個Bean以及它的父類中被@PreDestroy修飾的方法;
public static boolean hasApplicableProcessors(Object bean, ListpostProcessors) {
if (!CollectionUtils.isEmpty(postProcessors)) {
for (DestructionAwareBeanPostProcessor processor : postProcessors) {
//確定給定的 bean實例,有沒有定義銷毀邏輯
if (processor.requiresDestruction(bean)) {
return true;
}
}
}
return false;
}
· @PostConstruct和@PreDestroy注解的掃描,是在buildLifecycleMetadata()方法中完成并進(jìn)行分類緩存的,這一步驟在創(chuàng)建Bean過程中的初始化階段就已完成,這里只需要判斷是否有@PreDestroy定義的銷毀方法,判斷當(dāng)前Bean是否需要銷毀;
public boolean requiresDestruction(Object bean) {
return findLifecycleMetadata(bean.getClass()).hasDestroyMethods();
}
private LifecycleMetadata findLifecycleMetadata(Class>clazz) {
if (this.lifecycleMetadataCache == null) {
// Happens after deserialization, during destruction...
return buildLifecycleMetadata(clazz);
}
// Quick check on the concurrent map first, with minimal locking.
LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
synchronized (this.lifecycleMetadataCache) {
metadata = this.lifecycleMetadataCache.get(clazz);
if (metadata == null) {
metadata = buildLifecycleMetadata(clazz);
this.lifecycleMetadataCache.put(clazz, metadata);
}
return metadata;
}
}
return metadata;
}
2.注冊DisposableBean注冊銷毀的Bean,disposableBeans中緩存的是DisposableBeanAdapter對象,而不是當(dāng)前正在創(chuàng)建的Bean對象,無論該Bean是實現(xiàn)了DisposableBean或AutoCloseable接口,或者是通過BeanDifinition后置處理指定了”(inferred)“銷毀方法名或其它名字的銷毀方法, 還是通過@PreDestroy指定了銷毀方法,這里都會將Bean適配成一個DisposableBeanAdapter對象;
// 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));
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
說明:這里涉及到一個設(shè)計模式:適配器模式 ,在銷毀時,Spring會找出定義了銷毀邏輯的Bean。 但是我們在定義一個Bean時,如果這個Bean實現(xiàn)了DisposableBean接口,或者實現(xiàn)了 AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么這個Bean都屬 于“DisposableBean”,這些Bean在容器關(guān)閉時都要調(diào)用相應(yīng)的銷毀方法。 所以,這里就需要進(jìn)行適配,將實現(xiàn)了DisposableBean接口、或者AutoCloseable接口等適配成實現(xiàn)了DisposableBean接口,所以就用到了DisposableBeanAdapter。
DisposableBeanAdapter的構(gòu)造方法
在DisposableBeanAdapter的構(gòu)造方法中,會推斷出銷毀方法,并過濾出所有實現(xiàn)了DestructionAwareBeanPostProcessor接口且requiresDestruction()方法返回true的DestructionAwareBeanPostProcessor,銷毀的時候會調(diào)用它們的postProcessBeforeDestruction()方法;
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
ListpostProcessors, @Nullable AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean =
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
else {
if (destroyMethod.getParameterCount() >0) {
Class>[] paramTypes = destroyMethod.getParameterTypes();
if (paramTypes.length >1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
}
this.destroyMethod = destroyMethod;
}
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
private static ListfilterPostProcessors(
Listprocessors, Object bean) {
ListfilteredPostProcessors = null;
if (!CollectionUtils.isEmpty(processors)) {
filteredPostProcessors = new ArrayList<>(processors.size());
for (DestructionAwareBeanPostProcessor processor : processors) {
if (processor.requiresDestruction(bean)) {
filteredPostProcessors.add(processor);
}
}
}
return filteredPostProcessors;
}
二、Bean銷毀過程
1.容器關(guān)閉在Spring容器關(guān)閉的時候,會去銷毀所有的單例Bean,只要是單例對象,不管有沒有定義銷毀的邏輯,都是要銷毀的,只是定義了銷毀邏輯的單例Bean在銷毀之前,Spring會調(diào)用它們定義的銷毀邏輯,Spring容器關(guān)閉觸發(fā)Bean銷毀的兩種方式,如下:
ApplicationContext context= new AnnotationConfigApplicationContext(AppConfig.class);
//spring容器關(guān)閉的時候,會觸發(fā)銷毀方法
context.close();
//不用手動調(diào)用context.close()方法,可以向JVM里面注冊一個關(guān)閉鉤子,這樣也可以觸發(fā)銷毀方法,,這個關(guān)閉鉤子就是一個線程
context.registerShutdownHook();
以上兩種方式,都會調(diào)用doClose(),doClose()會去調(diào)執(zhí)行銷毀Bean的方法。
2.執(zhí)行doClose()doClose()中會調(diào)用destroyBeans(),而在destroySingletons()中會取出disposableBeans緩存中定義了銷毀邏輯的Bean的beanName,然后遍歷進(jìn)行銷毀
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
在進(jìn)行銷毀的時候,先從單例池等緩存中移除Bean,然后從disposableBeans移除當(dāng)前DisposableBean并獲取該對象,最后調(diào)用destroyBean(beanName, disposableBean)執(zhí)行對象的銷毀邏輯;在銷毀當(dāng)前Bean的時候,會獲取依賴當(dāng)前Bean的其他Bean的beanName,然后遞歸調(diào)用destroySingleton()方法,保證依賴當(dāng)前Bean的其他Bean先銷毀,在進(jìn)行銷毀時,會先調(diào)用DisposableBean的destroy()方法,然后再去調(diào)用其它的銷毀邏輯,其它的銷毀邏輯基本就是從各種緩存中根據(jù)BeanName,清除緩存;
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);
}
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// dependentBeanMap表示某bean被哪些bean依賴了
// 所以現(xiàn)在要銷毀某個bean時,如果這個Bean還被其他Bean依賴了,那么也得銷毀其他Bean
// Trigger destruction of dependent beans first...
Setdependencies;
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName);
}
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...
if (bean != null) {
try {
//會調(diào)用DisposableBeanAdapter對象的destory方法
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...
SetcontainedBeans;
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.
synchronized (this.dependentBeanMap) {
for (Iterator>>it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
Map.Entry>entry = it.next();
SetdependenciesToClean = entry.getValue();
dependenciesToClean.remove(beanName);
if (dependenciesToClean.isEmpty()) {
it.remove();
}
}
}
// Remove destroyed bean's prepared dependency information.
this.dependenciesForBeanMap.remove(beanName);
}
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
新聞標(biāo)題:Spring之Bean生命周期源碼解析-Bean銷毀-創(chuàng)新互聯(lián)
分享網(wǎng)址:http://muchs.cn/article48/cdohep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、網(wǎng)站設(shè)計、靜態(tài)網(wǎng)站、網(wǎng)站策劃、外貿(mào)建站、自適應(yīng)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容