Spring 源碼梳理(三) 再談BeanPostProcessor

再談BeanPostProcessor

上篇文章介紹的是BeanPostProcessor的用法,在最後留下了一個問題,對於Spring中的Bean屬性'Lazy-init'(延遲加載),當Hook類(BeanPostProcessorApp)或被Hook的類(App)具有這個屬性時,會有什麼樣的表現。

1.接着前面文章的已有的配置,首先我們分別在App和BeanPostProcessorApp上增加構造函數,並且打印一句話:

private App(){
		System.out.println("App.App()");
	}
private BeanPostProcessorApp(){
		System.out.println("BeanPostProcessorApp.BeanPostProcessorApp()");
	}

同時在BeanPostProcessorApp中增加一個after方法(上篇只用到了before):

public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		if(bean instanceof App){
			((App)bean).setSays("After:BeanPostProcessorApp");
		}
		return bean;
	}

然後執行BeanPostProcessorAppTest方法,打印的結果如下:

BeanPostProcessorApp.BeanPostProcessorApp()
App.App()
App.app():After:BeanPostProcessorApp


2.我們調式看一下三條信息分別在什麼情況下產生:

1)剛纔的第一條信息 “BeanPostProcessorApp.BeanPostProcessorApp() ”是在registerBeanPostProcessors()方法中產生的,也就是說該BeanPostProcessorApp的初始化是在所有BeanPostProcessor註冊的時候就進行了。


而這個時候Bean的實例化還沒有開始,所以得出這樣的結論:

在實現BeanPostProcessor的接口的Bean中增加lazy-init屬性是無效的,因爲這個Bean在未進行初始化的時候已經被上面的registerBeanPostProcessors初始化了;結合本例,也就是說下面的寫法是無效的:


2)再看第二條信息,因爲沒有設置lazy-init屬性,所以在finishBeanFactoryInitialization()方法中就進行了初始化並且創建了實例,如下:


3)最後一條信息則是這樣產生的,因爲我們在註冊BeanPostProcessor的時候已經把我們自己的BeanPostProcessorApp註冊了,同時在執行finishBeanFactoryInitialization方法進行Bean的初始化的時候會執行org.springframework.beans.factory.support.AbstractBeanFactory中的getBean方法(上一篇已經介紹了),創建一個實例,進行真正的注入,而我們的

<span style="font-family:SimSun;">App app = (App)applicationContext.getBean("app");</span>

只是得到其中一個引用,最後打印信息。

3.上面分析的結論是,在實現BeanPostProcessor的接口的Bean中增加lazy-init屬性是無效的,可以自己實例驗證一下,這裏就不貼上了;繼續分析,如果我們給Bean App增加lazy-init這個屬性呢?,如下:


我們可以猜測,因爲加上lazy-init屬性之後,就不會在Spring的初始化過程中實例化;在org.springframework.beans.factory.support.DefaultListableBeanFactory(上一篇提到過)中我們可以看到,實際上是沒有執行org.springframework.beans.factory.support.AbstractBeanFactory的getBean方法:


而這個org.springframework.beans.factory.support.AbstractBeanFactory中的getBean方法實際上是執行了“實例化”+"BeanPostProcessor"這兩個功能。

所以猜測1:加載完Spring配置文件不會有第二條信息。

由於我們寫的getBean其實就是org.springframework.beans.factory.support.AbstractBeanFactory中的getBean,如下:


所以猜測2:執行完自己的getBean就會進行初始化,並且執行BeanPostProcessor的實現;

驗證如下:


如上,證實了猜測1


如上圖,在未執行第三個斷點says方法之前,says的值已經改變,證實了猜測2.

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