Spring Bean生命周期


前言

Spring Bean生命周期是常見的面試題,也是日常開發中經常用到的技術點,在應用開發中,常常需要執行一些特殊的初始化工作,如建立數據庫連接,打開網絡連接,又比如在一些業務bean里,你想拿到Spring IOC容器,又或者是想拿到一些已經實例化的Bean。同時,在服務結束時,也有一些銷毀銷毀工作需要執行。為了便於工作的設計,Spring IOC提供相關接口,可以讓應用定制Bean的初始化和銷毀。

Spring Bean生命周期

先來看一下Spring Bean生命周期流程圖,方便對照后續的源碼分析。
Spring 生命周期.jpg
Spring Bean生命周期從大的節點上分為4個過程:實例化、屬性賦值、初始化、銷毀。 日常業務開發過程中,我們應該涉及最多的兩個點就是初始化和銷毀,比如自定義Bean實現InitializingBean、DisposeableBean。

源碼分析

Spring IOC容器初始化

初始化從AbstractAutowireCapableBeanFactory.doCreateBean方法開始說起,我在對應的代碼位置標注了關鍵點

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
	}
    
	//1. Bean實例化
	if (instanceWrapper == null) {
	   instanceWrapper = this.createBeanInstance(beanName, mbd, args);
	}

	Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	synchronized(mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			} catch (Throwable var17) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
			}

			mbd.postProcessed = true;
		}
	}

	boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
	if (earlySingletonExposure) {
		this.addSingletonFactory(beanName, () -> {
			return this.getEarlyBeanReference(beanName, mbd, bean);
		});
	}

	Object exposedObject = bean;

	try {
	    //2.屬性賦值
       this.populateBean(beanName, mbd, instanceWrapper);
	    //3.初始化
	    exposedObject = this.initializeBean(beanName, exposedObject, mbd);
	} catch (Throwable var18) {
	    if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
		throw (BeanCreationException)var18;
	    }

	    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
	}

	if (earlySingletonExposure) {
		Object earlySingletonReference = this.getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
				String[] dependentBeans = this.getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
				String[] var12 = dependentBeans;
				int var13 = dependentBeans.length;

				for(int var14 = 0; var14 < var13; ++var14) {
					String dependentBean = var12[var14];
					if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}

				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	try {
	    //4.銷毀 - 注冊回調接口
	    this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
	    return exposedObject;
	} catch (BeanDefinitionValidationException var16) {
	    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
	}
}

為了保持代碼片段精簡,我刪掉了其中的logger代碼。

從以上代碼片段里可以看到我們上面總結的Spring生命后期4個關鍵點都有體現,我們着重分析初始化和銷毀流程。

AbstractAutowireCapableBeanFactory.initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	//1.檢查Aware相關接口並設置相關依賴
    //BeanNameAware, BeanClassLoaderAware, BeanFactoryAware
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(() -> {
			this.invokeAwareMethods(beanName, bean);
			return null;
		}, this.getAccessControlContext());
	} else {
		this.invokeAwareMethods(beanName, bean);
	}

    //2.BeanPostProcessor前置處理
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
	    //BeanPostProcessor接口的postProcessBeforeInitialization回調
		wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
	}
    
	//3.若實現InitializingBean接口,則調用afterPropertiesSet()
	//4.若配置自定義的init-method(), 則執行。
	try {
		this.invokeInitMethods(beanName, wrappedBean, mbd);
	} catch (Throwable var6) {
		throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
	}

    //5.BeanPostProcessor后置處理
	if (mbd == null || !mbd.isSynthetic()) {
	    //BeanPostProcessor接口的postProcessAfterInitialization回調
		wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

AbstractAutowireCapableBeanFactory.invokeAwareMethods
invokeAwareMethod就是調用一系列Aware結尾的接口,比如
BeanNameAware、ApplicationContextAware、BeanFactoryAware。

private void invokeAwareMethods(String beanName, Object bean) {
   if (bean instanceof Aware) {
      if (bean instanceof BeanNameAware) {
         ((BeanNameAware)bean).setBeanName(beanName);
      }

       if (bean instanceof BeanClassLoaderAware) {
           ClassLoader bcl = this.getBeanClassLoader();
           if (bcl != null) {
               ((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
           }
       }

       if (bean instanceof BeanFactoryAware) {
           ((BeanFactoryAware)bean).setBeanFactory(this);
       }
   }
 }

AbstractAutowireCapableBeanFactory.invokeInitMethods
invokeinitMethods就是調用InitializingBean接口的afterPropertiesSet,並且檢查自定義init-method。

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
	boolean isInitializingBean = bean instanceof InitializingBean;
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged(() -> {
					((InitializingBean)bean).afterPropertiesSet();
					return null;
				}, this.getAccessControlContext());
			} catch (PrivilegedActionException var6) {
				throw var6.getException();
			}
		} else {
			((InitializingBean)bean).afterPropertiesSet();
		}
	}

	if (mbd != null && bean.getClass() != NullBean.class) {
		String initMethodName = mbd.getInitMethodName();
		if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
			this.invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

從以上代碼片段可以看出Spring IOC容器創建Bean的過程, 涉及的過程包括實例化,銷毀,還包括BeanPostProcessor接口相關方法實現,以上代碼片段我們分析了Spring容器初始化過程加載Bean的各種實現,下面我們看下Spring容器銷毀階段。

容器銷毀

Spring容器銷毀過程調用鏈
Spring 生命周期 Bean銷毀 調用鏈.jpg
Spring在這里用了適配器模式,也就是說最終的銷毀任務由DisposableBeanAdapter來完成,我們看下DisposeableBeanAdapter的結構。
截屏2021-05-15 09.14.27.png
從結構中可以看到bean屬性類型為Object, 也就是要銷毀的Bean,還有beanName屬性。

public void destroy() {
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        Iterator var1 = this.beanPostProcessors.iterator();

        while(var1.hasNext()) {
            DestructionAwareBeanPostProcessor processor = (DestructionAwareBeanPostProcessor)var1.next();
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }

	if (this.invokeDisposableBean) {
		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged(() -> {
					((DisposableBean)this.bean).destroy();
					return null;
				}, this.acc);
			} else {
				((DisposableBean)this.bean).destroy();
			}
		} catch (Throwable var3) {
			
		}
	}

	if (this.destroyMethod != null) {
		this.invokeCustomDestroyMethod(this.destroyMethod);
	} else if (this.destroyMethodName != null) {
		Method methodToInvoke = this.determineDestroyMethod(this.destroyMethodName);
		if (methodToInvoke != null) {
			this.invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
		}
	}
}

總結

Spring Bean生命周期分為4個階段和多個擴展點,擴展點又分為影響多個Bean和單個Bean。
4個階段:實例化、屬性賦值、初始化、銷毀。
擴展點
影響多個Bean

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor

影響單個Bean

  • BeanNameAware
  • BeanFactoryAware
  • BeanClassLoaderAware
  • ApplicationContextAware

Spring生命周期中兩個關鍵的接口:InitializingBean, DisposableBean。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM