1. 程式人生 > >做一個合格的程式猿之淺析Spring IoC原始碼(十一)Spring refresh()方法解析後記1

做一個合格的程式猿之淺析Spring IoC原始碼(十一)Spring refresh()方法解析後記1

上次分析refresh這塊spring IoC的時候,時間比較倉促,只是debug了部分原始碼,大家分析起來不是很好~

今天我們還是先總結一下吧~

spring在例項化bean的時候,根據bean實現的介面不同,bean的例項化也是有先後順序的

由於此塊程式碼太多,貼圖給大家的學習的效果不好,現在以spring 3.2.5原始碼為例,大家再一份“溫故”一下,然後“知新”

①:開啟AbstractApplicationContext.java中refresh()先初始化好beanFactory(DefaultListableBeanFactory.java)【第445行~第496行】:

這邊先對beanFactory做好初始化,關於beanFactory的初始化前面已經講過了,連結如下:

http://blog.csdn.net/linuu/article/details/50829981

②初始化好了beanfactory之後,就先開始處理實現BeanFactoryPostProcessor.java的bean,說明BeanFactoryPostProcessor的例項化的優先順序最高


    2.1 原因:實現了BeanFactoryPostProcessor.java這個介面的bean需要具體的實現BeanFactoryPostProcessor中定義的介面postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)這個介面。

        而這個介面可以直接修改beanDefinitionMap中beanDefinition中儲存的bean的資訊,而beanDefinition是所有bean初始化的依據,也就是說所有bean依賴於beanDefinition,所以實現BeanFactoryPostProcessor的介面的bean優先初始化,這樣如果該bean修改了其他bean的beanDefinition,其他bean在後面初始化的時候才能按照使用者給的正確引數例項化,例如org.springframework.beans.factory.config.PropertyPlaceholderConfigurer這個類(該類具體作用參照連結:http://blog.csdn.net/linuu/article/details/50853687)

   2.2 如果開啟461行的程式碼,你會發現,如果有多個bean實現了BeanFactoryPostProcessor介面,那麼這些bean的初始化順序也是有講究的

       AbstractApplicationContext.java 【605行~685行中】

     2.2.1首先例項化的是實現BeanDefinitionRegistryPostProcessor這個介面的bean(很好理解,看字面就知道,這個介面要修改的就是BeanDefinition,不先正確的例項化好它,例項化好,因為這個也許是其他bean的依賴注入呢),官方註釋

 

  (if any,說明了什麼,說明了它比誰都的優先順序都高)

    2.2.2 接著看註釋:

接著按照字面的理解,同樣,如果多個bean實現了BeanFactoryPostProcessor的情況下,誰實現了PriorityOrdered介面,誰也是優先執行,當然在實現BeanDefinitionRegistryPostProcessor這個之後

然後是實現了Ordered.java的介面,最後就是沒有實現這2個特殊介面的普通實現BeanFactoryPostProcessor的bean了

    2.3 實現了BeanFactoryPostProcessor這個介面的bean,例項化的時候,第一件事情就是先把自己例項化,把自己例項化後才可以去做實現BeanFactoryPostProcessor這個介面定義的事情,這就是為什麼下圖中①模組比②模組先列印的原因了:

③ 現在我們開始分析上圖中①的執行順序,首先①模組執行的入口是

追蹤getBean這個方法,我們會追蹤到AbstractBeanFactory.java 的第230行doGetBean()這個方法

這塊程式碼的執行順序是:

3.1 首先先去例項化好的bean中去找,如果找到,直接返回【234行~250行】

3.2 然後去當前beanfactory中父類factory找,如果能找到父類的factory,則叫父類去返回,(與jvm的classloader的雙親載入比較像~)【260行~272行】

3.3 如果都沒有找到,則開始初次例項化,先標記開始例項化【274~276行】

3.4 開始檢視當前要例項化的bean是否依賴於其他的bean,如果依賴,則先例項化依賴的bean,如果依賴的bean還依賴於其他的bean,則接著遞迴建立

3.5如果建立的bean是單例(spring預設單例)接著建立


開啟createBean,一直追蹤到AbstractAutowireCapableBeanFactory.java的1030行,此時已經對該bean在spring的名片beandefinition中的class已經做了初步的校驗,例如該類是否是private是否是abstract是否有預設的建構函式等等,符合校驗後直接根據java的反射進行建立(當然此類不是介面),建立的物件經過spring包裝返回一個BeanWrapper

因為此時bean已經建立了,所以下圖中紅色框框已經打印出來:

我們接著看AbstractAutowireCapableBeanFactory.java這個方法的第480行doCreateBean()這個方法的

此時我們已經建立好了bean了,我們要做的事還有Setter值,beanNameAware beanFactoryAware,initMethod(這些前幾篇部落格有介紹)這些建立後的“動作”

好的,接著看519行:populateBean這個方法(開始setter值)


因為setter可以根據多個屬性setter注入,我們這邊就不分析了,我們追蹤到AbstractAutowireCapableBeanFactory.java的1368行applyPropertyValues這邊的程式碼塊

setter好後,執行521行程式碼,進入initializeBean這個方法

這個方法一開始if else都要執行invokeAwareMethods這個方法,對Aware我們很熟悉,進入檢視

是的,首先執行實現BeanNameAware介面的setBeanName方法,然後是實現BeanClassLoaderAware的setBeanClassLoader方法,最後是實現BeanFactoryAware這個bean的方法

好了,跟我們列印的順序是一致的:

我們接著看initializeBean這個方法

BeanPostProcessor需要註冊才能執行,這邊暫不分析,所以先看1509行程式碼invokeInitMethods,進入看:


如果該bean實現了InitializingBean介面,則先執行afterPropertiesSet()方法,最後


最後執行了我們在spring-init.xml中自定義的

所以最後列印了:

如上圖中①模組所示,關於②模組下次再解析,這篇主要是對上篇日記的補充,不好意思,上次解析太多粗糙了,希望這篇對大家有幫助,END~