spring的後置處理器(未完結版)

學習spring源碼也有一階段時間了,是時候收貨的季節了,打算寫幾篇博客,把自己的知識沉澱下來。在學習spring的源碼之前,別人問我spring什麼牛逼。我會毫不猶豫的說出AOP,IOC啊。但是看看源碼之後,我覺得spring的後置處理器真牛逼,大名鼎鼎的AOP就利用了BeanPostProcessor和IOC容器建立了聯繫。不知道幾個spring的後置處理器,你真不好意思說你學過spring。後置處理器就是LOL玩家姿態口中的"核心玩家"(不懂這個梗的可以忽略這句)。那麼這篇博客將從下面這四個問題出發,從源碼和應用的角度,剖析spring的後置處理器。

1.什麼是後置處理器,有啥用?

2.spring什麼時候註冊的後置處理器?

3.spring什麼時候執行後置處理器?

4.這些spring的後置處理器有哪些應用場景?

1.什麼是後置處理器,有啥用?

大家想必都知道這樣的一個設計原則:開閉原則,對擴展開放,對修改關閉。

那麼spring的後置處理器就完美詮釋了這一特性,簡單來說,spring的後置處理器就是提供一個接口,讓你干預bean的實例化,讓你在bean的實例化前後擴展bean。

我們看下spring都提供了那些後置處理器。

先來看看大家都耳熟能詳的一個接口:BeanPosterProcess

public interface BeanPostProcessor {

	/**
	 * 在bean初始化之前執行
	 */
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * 初始化之後
	 */
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

這個就是BeanPostProcessor接口,就倆方法,簡單到讓人髮指,但是他的實現類,多的讓人髮指(電腦屏幕有限,只能截取這些)

當然這些不可能都要掌握,我只能挑幾個我熟悉的,常見的來學習下。我們來介紹幾個常見的後置處理器

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor接口繼承BeanPostProcessor接口,它內部提供了3個方法,再加上BeanPostProcessor接口內部的2個方法,所以實現這個接口需要實現5個方法。InstantiationAwareBeanPostProcessor接口的主要作用在於目標對象的實例化過程中需要處理的事情,包括實例化對象的前後過程以及實例的屬性設置

在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean()方法的Object bean = resolveBeforeInstantiation(beanName, mbdToUse);方法裏面執行了這個後置處理器

1、postProcessBeforeInstantiation

在目標對象實例化之前調用,方法的返回值類型是Object,我們可以返回任何類型的值。由於這個時候目標對象還未實例化,所以這個返回值可以用來代替原本該生成的目標對象的實例(一般都是代理對象)。如果該方法的返回值代替原本該生成的目標對象,後續只有postProcessAfterInitialization方法會調用,其它方法不再調用;否則按照正常的流程走

2、postProcessAfterInstantiation

方法在目標對象實例化之後調用,這個時候對象已經被實例化,但是該實例的屬性還未被設置,都是null。如果該方法返回false,會忽略屬性值的設置;如果返回true,會按照正常流程設置屬性值。方法不管postProcessBeforeInstantiation方法的返回值是什麼都會執行

3、postProcessPropertyValues

方法對屬性值進行修改(這個時候屬性值還未被設置,但是我們可以修改原本該設置進去的屬性值)。如果postProcessAfterInstantiation方法返回false,該方法不會被調用。可以在該方法內對屬性值進行修改

4、postProcessBeforeInitialization&postProcessAfterInitialization

父接口BeanPostProcessor的2個方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目標對象被實例化之後,並且屬性也被設置之後調用的

SmartInstantiationAwareBeanPostProcessor

智能實例化Bean後置處理器(繼承InstantiationAwareBeanPostProcessor)

1、determineCandidateConstructors

檢測Bean的構造器,可以檢測出多個候選構造器

2、getEarlyBeanReference

循環引用的後置處理器,這個東西比較複雜, 獲得提前暴露的bean引用。主要用於解決循環引用的問題,只有單例對象纔會調用此方法

3、predictBeanType

預測bean的類型

三、MergedBeanDefinitionPostProcessor

1、postProcessMergedBeanDefinition

緩存bean的注入信息的後置處理器,僅僅是緩存或者乾脆叫做查找更加合適,沒有完成注入,注入是另外一個後置處理器的作用

 

 

2.spring什麼時候註冊的後置處理器?(明天詳細介紹)

3.spring什麼時候執行後置處理器?(有些細節明天還要在深入,今天已經很晚了)

我的知識世界裏,spring在bean的實例化前後,一個有8處調用了spring的後置處理器。我們從源碼的角度來看,把這9處處理器執行過程,找出來,我今天就下播,睡覺,明天還要上班。

第一次:

我們看下這個InstantiationAwareBeanPostProcessor到底起着什麼作用

如果該方法的返回值代替原本該生成的目標對象,後續只有postProcessAfterInitialization方法會調用,其它方法不再調用;否則按照正常的流程走

第二次:

SmartInstantiationAwareBeanPostProcessor這個後置處理器也非常重要,你的bean要用哪個構造方法去創建對象,都可以通過這個後置處理器來指定。我們來舉個例子,在service下面提供兩個構造方法,看看執行結果。

第一種情況是,提供兩個構造方法有參和無參

打印的是no說明用的是這個無參的構造方法。

改變下這個類的構造方法,加一個註解

在構造方法上添加一個@Autowired的註解,就會調用另外一個構造方法,那我們把兩個方法都加上註解呢,spring會知道用哪一個呢?

不好意思,spring也懵逼了,不知道到底用哪個,就報錯了。這其實很容易理解,如果有兩個美女(劉亦菲,劉詩詩)讓你選擇,你個貪心的傢伙選擇想兩個都要,最後結果可想而知,你會J盡人亡。那麼下面我們進入spring的源碼來看下這到底是是真怎麼實現的。

  

 

 

 

第三次

第四次

第五次

第六次

第七次

第八次

4.這些spring的後置處理器有哪些應用場景?(明天詳細介紹)

知道了spring的後置處理器是什麼,而且知道了spring的後置處理器在什麼情況下調用,我們來用實際的案例來分析一下spring的這幾種後置處理器(注意,前方高能,涉及的內容比較多,瞭解了,出去和面試官可以隨便吹逼)

1.InstantiationAwareBeanPostProcessor的使用場景

我們都知道spring的動態代理

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