前言
在多次對Spring的源碼斷點調試以及瞭解ApplicationContext的結構之後,發現無論是ClassPathXmlApplicationContext還是FileSystemXmlApplicationContext的初始化最終會指向AbstractApplicationContext的refresh()方法。
AbstractApplicationContext是一個抽象類別,這個類繼承了DefaultResourceLoader類,實現了ConfigurableApplicationContext和DisposableBean這2個介面。為什麼要使用抽象類別呢。
我個人對於這種繼承某個類,然後實現多個介面的做法的理解是通過使用抽象類別提供預設的實現或者是公用的邏輯。
PS:本人學習的Spring源碼版本為4.2.3.RELEASE,如果看到與文章內容不一致,可能是不同版本的實現方案不同 refresh()方法解讀
@Overridepublic void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //為Context的重新整理準備 prepareRefresh(); //讓子類重新整理內部的BeanFactory,其實就是讓子類調用refreshBeanFactory()方法的地方 //refreshBeanFactory()是個抽象方法,需要子類實現 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //準備用於Context的BeanFactory prepareBeanFactory(beanFactory); try { //設定BeanFactory的BeanFactory後置處理器 //postProcessBeanFactory()方法是個空實現,允許開發人員通過重寫自訂自己的後置處理器 postProcessBeanFactory(beanFactory); //調用BeanFactory的後置處理器處理BeanFactory執行個體 invokeBeanFactoryPostProcessors(beanFactory); //將Bean的後置處理器註冊到上下文(Context)的BeanFactory執行個體 //Bean的後置處理器是用於攔截Bean的建立,並對建立後的Bean執行個體進行處理 registerBeanPostProcessors(beanFactory); //初始化內容相關的訊息資源 initMessageSource(); //初始化應用內容相關的事件接收器 //說明Spring是基於事件機制 initApplicationEventMulticaster(); //初始化其他特殊的Bean //這個方法是空實現,允許開發人員通過重寫添加自訂的Bean onRefresh(); //檢查監聽器Bean並將這些Bean執行個體註冊到上下文 registerListeners(); //初始化所有非懶載入的單例對象 finishBeanFactoryInitialization(beanFactory); //發布容器重新整理完成事件,完成重新整理過程 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } //銷毀所有已經建立的單例對象,避免Bean資源佔用 destroyBeans(); //取消重新整理,重設active標識(置為false) cancelRefresh(ex); //將異常傳給調用者 throw ex; } finally { //重設Spring中內建的自檢緩衝,其實就是清空緩衝 resetCommonCaches(); } }} 心得體會
Spring中的BeanFactory算不算是Spring的Bean呢。
BeanFactory算Spring的Bean,不過BeanFactory是先初始化之後再註冊到Spring的上下文,雖然BeanFactory本身也是Spring內容相關的一部分。詳情可以參考AbstractApplicationContext的refresh方法中調用的prepareBeanFactory、postProcessBeanFactory、invokeBeanFactoryPostProcessors、registerBeanPostProcessors這幾個方法。
Spring的上下文初始化的時候只會初始化非懶載入的單例對象(參考finishBeanFactoryInitialization()方法),這是因為懶載入的單例對象本身就應該在使用到的時候才進行初始化,而多例對象則是由於不清楚會有多少個對象或者線程使用到,所以也會在使用時候建立。