Spring系列之實例化、初始化處理器

概念

談論到實例化處理器和初始化處理器,我們要明確一個實例化和初始化概念,大牛們可以忽略此處說明。

  • 實例化:指創建類實例(對象)的過程。比如使用構造方法new對象,爲對象在內存中分配空間。(要創建對象,但是並未生成對象)
  • 初始化:指爲類中各個類成員(被static修飾的成員變量)賦初始值的過程,是類生命週期中的一個階段。簡單理解爲對象中的屬性賦值的過程。(對象已經生成,爲其屬性賦值)

源碼

從源碼解讀實例化處理器和初始化處理器。

  1. InstantiationAwareBeanPostProcessor
    該接口繼承自BeanPostProcessor接口,並自定義如圖方法。
    在這裏插入圖片描述
  • postProcessBeforeInstantiation 實例化前置處理 (對象未生成)
  • postProcessAfterInstantiation 實例化後置處理 (對象已經生成)
  • postProcessPropertyValues 修改屬性值。(對象已經生成)
  1. BeanPostProcessor
    在這裏插入圖片描述
  • postProcessBeforeInitialization初始化前置處理 (對象已經生成)
  • postProcessAfterInitialization初始化後置處理 (對象已經生成)

觸發處理器時機

從Bean的生命週期流程中可知,實例化和初始化處理器作用時機主要在初始化Bean前後。
主要在類AbstractAutowireCapableBeanFactory

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;
		//根據設置的class屬性或者根據className來解析class:調用AbstractBeanFactory類
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		// Prepare method overrides.
		try {
			//驗證以及準備覆蓋的方法即Override方法
			mbdToUse.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}
		try {
			//返回代理來代替真正的實例:--------------應用實例化前的前置處理器
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			//短路操作,返回bean
			if (bean != null) {
				//返回bean的代理對象
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		//---------------創建單例bean對象:核心方法doCreateBean(常規bean的創建過程)
		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
		catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
			// A previously detected exception with proper bean creation context already,
			// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
		}
	}
  1. 觸發postProcessBeforeInstantiation時機
    postProcessBeforeInstantiation調用時機: BeanDefinition創建Bean的開端是在createBean()方法也就是流水線的開始處。
    注意是否返回bean的代理對象,如果返回Bean的代理對象,則直接return代理對象;即resolveBeforeInstantiation()方法,源代碼如下
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			//是否實現前置處理器接口
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					//調用InstantiationAwareBeanPostProcessor:實例化前置處理器
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						//調用初始化後置處理器,doCreateBean流程結束
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

解釋說明:

  • 首先,判斷是否存在InstantiationAwareBeanPostProcessor接口的處理器
  • 如存在,則調用的是InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()實例化前置處理方法,也就是在Bean對象沒有生成之前執行(實例化過程中)。(注意:這裏所說的是Bean未生成指的是Bean沒有走spring定義創建Bean的流程,也就是doCreateBean()方法。)
  • 如果postProcessBeforeInstantiation()返回的對象不爲空, 意味着Bean對象已經存在,表明對象已經初始化完成。然後調用postProcessAfterInitialization()初始化後置處理器,完成對Bean對象的操作.
    如果postProcessBeforeInstantiation()返回值爲空,則進入上層調用者createBean()方法,繼續調用doCreateBean()方法,完成對象實例化(創建對象),以及對象初始化.
  1. postProcessAfterInstantiation調用時機
    上面createBean()方法中標識若resolveBeforeInstantiation()方法沒有返回bean,則調用doCreateBean()方法,進入創建bean流程中;
    下面我們開始分析doCreateBean()的部分代碼
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {
			...//省略部分源碼
		// Initialize the bean instance.
		//------------------------完成實例化bean創建,下面開始進行------bean初始化操作-------------
		Object exposedObject = bean;
		try {
			//----****屬性填充操作:其中可能會存在依賴其他bean屬性,則會遞歸初始化依賴bean****
			populateBean(beanName, mbd, instanceWrapper);
			//--- ****初始化指定的bean實例*****,回調init()方法和執行處理器
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}
		...//省略後面代碼
		}

跟蹤populateBean()方法的源碼實現,便可以發現postProcessAfterInstantiation() 與postProcessPropertyValues()依次被執行。該方法仍然處於實例化過程

...省略部分源碼
//是否實現InstantiationAwareBeanPostProcessor接口,以及bean是否依賴檢查
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		//處理實現了InstantiationAwareBeanPostProcessor
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (BeanPostProcessor bp : getBeanPostProcessors()) {
				//一次調用實現的InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues方法
				if (bp instanceof InstantiationAwareBeanPostProcessor) {
					InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
					PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						if (filteredPds == null) {
							filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
						}
						pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
						if (pvsToUse == null) {
							return;
						}
					}
					pvs = pvsToUse;
				}
			}
		}
  1. postProcessBeforeInitialization、 postProcessAfterInitialization
    初始化前後處理器,從initializeBean()方法中依次被調用執行
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//如果bean是BeanNameAware,BeanClassLoaderAware或者BeanFactoryAware其中某一個的實現類就需要進行處理
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}
		Object wrappedBean = bean;
		//bean生命週期之一:如果實現了BeanPostProcessor接口,則會在此調用實現類中的beanPostProcessorsBeforeInitialization()方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			//bean生命週期之一:如果實現InitializingBean接口,則會在此調用實現類中的afterPropertiesSet()方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		//bean生命週期之一:如果實現了BeanPostProcessor接口,則會在此調用實現類中的beanPostProcessorAfterInitialization()方法
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

總結

  1. BeanPostProcessor定義的方法是在對象初始化過程中做處理,分別在resolveBeforeInstantiation()觸發後置處理器,或者在initializeBean依次調用前後處理器。
  2. InstantiationAwareBeanPostProcessor定義的方法是在對象實例化過程中做處理,即分別在resolveBeforeInstantiation()、populateBean()觸發前置處理器,後置處理器。
    從上面分析可知:
    實例化—>初始化過程中會形成兩條路徑。
  • postProcessBeforeInstantiation()–自定義對象–>postProcessAfterInitialization();
  • postProcessBeforeInstantiation() -->postProcessAfterInstantiation–>postProcessBeforeInitialization()–>postProcessAfterInitialization()
    postProcessBeforeInstantiation一定執行, postProcessAfterInitialization一定執行.

參考資料:https://juejin.im/post/5da995d25188256a49204d7b

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章