spring源碼系列7:Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的區別


概念

Bean創建過程中的“實例化”與“初始化”名詞

  • 實例化(Instantiation): 要生成對象, 對象還未生成.
  • 初始化(Initialization): 對象已經生成.,賦值操作。

BeanPostProcessor :
發生在 BeanDefiniton 加工Bean 階段. 具有攔截器的含義. 可以攔截BeanDefinition創建Bean的過程, 然后插入攔截方法,做擴展工作.

  • postProcessBeforeInitialization初始化前置處理 (對象已經生成)
  • postProcessAfterInitialization初始化后置處理 (對象已經生成)

InstantiationAwareBeanPostProcessor: 繼承於BeanPostProcessor ,所以他也是一種參與BeanDefinition加工Bean過程的BeanPostProcessor攔截器, 並且豐富了BeanPostProcessor的攔截.

  • postProcessBeforeInstantiation 實例化前置處理 (對象未生成)
  • postProcessAfterInstantiation 實例化后置處理 (對象已經生成)
  • postProcessPropertyValues 修改屬性值。(對象已經生成)

總的來說:

BeanPostProcessor定義的方法是在對象初始化過程中做處理。
InstantiationAwareBeanPostProcessor定義的方法是在對象實例化過程中做處理

發生時機

1.postProcessBeforeInstantiation 調用時機
BeanDefinition創建Bean的開端是在createBean()方法也就是流水線的開始處。

	    @Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
		...省略
		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}

		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}

看這段英文注釋: Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

給BeanPostProcessor一個機會去返回一個代理對象. 就是在流水線doCreateBean()生成對象之前, 給用戶自定義返回一個對象的機會.

再看看resolveBeforeInstantiation(beanName, mbdToUse)是如何處理自定義返回對象的.

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
  • 判斷是有有InstantiationAwareBeanPostProcessor的BeanPostProcessor
  • 有則調用的是InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()實例化前置處理方法,也就是在Bean沒有生成之前執行。(注意:這里所說的是Bean未生成指的是Bean沒有走spring定義創建Bean的流程,也就是doCreateBean()方法。)
  • 如果postProcessBeforeInstantiation()返回的對象不為空, 那么對象的生成階段直接完成
  • 接着調用postProcessAfterInitialization()[初始化后置處理] 處理這個對象.
  • 如果為空?則走流水線doCreateBean()創建對象, 對象初始化.

2.postProcessAfterInstantiation調用時機

上文resolveBeforeInstantiation()沒有返回bean.則走流水線創建Bean

doCreateBean(beanName, mbdToUse, args)創建對象,會經過populateBean(beanName, mbd, instanceWrapper)方法。

populateBean(beanName, mbd, instanceWrapper)依次執行postProcessAfterInstantiation() postProcessPropertyValues()

3.postProcessBeforeInitialization調用時機

doCreateBean(beanName, mbdToUse, args)創建對象,會經過initializeBean(beanName, exposedObject, mbd);方法。

initializeBean(beanName, exposedObject, mbd); 會首先執行 postProcessBeforeInitialization()方法

4.postProcessAfterInitialization

initializeBean(beanName, exposedObject, mbd); 會首先執行 postProcessAfterInitialization()方法

總結:

實例化--->初始化

  • BeanPostProcessor定義的方法是在對象初始化過程中做處理。
  • InstantiationAwareBeanPostProcessor定義的方法是在對象實例化過程中做處理

會形成兩種執行流程完成BeanDefinition 創建Bean.

  1. postProcessBeforeInstantiation()--自定義對象-->postProcessAfterInitialization();
  2. postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessBeforeInitialization()-->postProcessAfterInitialization()

我們看出:postProcessBeforeInstantiation一定執行, postProcessAfterInitialization一定執行.

至此:不知道讀者是否體會到了InstantiationAwareBeanPostProcessor與BeanPostProcessor接口 以及其定義的4個方法的妙處.

四個方法執行的順序對理解spring創建流程有着重要意義。

BeanPostProcessor 本身就是一種攔截的設計思想. 攔截的目的就是做額外的操作, 即 擴展。

歡迎大家關注我的公眾號【源碼行動】,最新個人理解及時奉送。
在這里插入圖片描述


免責聲明!

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



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