spring源碼詳細總結


前言

上周線上項目出了一個bug,使用WebMvcConfigurer和WebMvcConfigurationSupport不能同時使用,要不然WebMvcConfigurer能掃描到容器中,但是他的方法不能執行。

只有搞懂了spring的源碼流程,才能對這個問題進行整體的把握。

ApplicationContext簡介

通過debug的方式對spirng源碼進行一步一步的解讀,spring的核心之一就是IOC容器,這是一個抽象的概念,對應IOC,做過spirng開發的想必都有所耳聞,但是對於他是什么大部分初級程序員是不明朗的。

IOC體現在spring中就是ApplicationContext,這是最重要的接口,spirng中有眾多的類實現了這個接口,不同的ApplicationContext在不同的應用場景使用。

AnnotationConfigApplicationContext是基於注解的方式啟動容器,ClassPathXmlApplicationContext是基於xml配置的方式啟動容器,其他還有許多的方式啟動容器,雖然多,但是能夠見名知意,名字都是**ApplicationContext。
spring-ioc容器核心啟動類繼承關系
類名有個簡單的印象就行,如果都看一遍太枯燥了,筆者也不推薦這樣做。

Beanfactory簡介

BeanFactory我的理解就是IOC容器中的一些工具方法,這是我淺顯的理解,下圖是BeanFactory 的所有方法,ApplicationContext繼承了這個接口。
Beanfactory全部方法

啟動過程

通過debug的方式一步步深挖spring源碼,一定要自己debug要不然很累!一定要自己debug要不然很累!一定要自己debug要不然很累!重要事情說三遍。

先通過一個簡單的樣例,看下spring-ico的一個簡單使用。這個方法的作用就是new了一個ApplicationContext傳入一個定義的bean,然后通過getBeanDefinitionNames()獲取到它的容器中所有的bean。
在這里插入圖片描述
在這里插入圖片描述
點進去ApplicationContext的構造方法,會發現它調用了一個refresh()方法,這個方法是spring-ico最核心的方法,IOC初始化、注冊bean等等一系列方法都是這這里完成的。

值得一提的是,springboot的run方法一步步點進去調用的還是這個refresh方法,看到這相信大家對於spirng和springboot的關系有了一個模糊的認識。
springboot-run方法
透過現象看本質,其實springboot的核心啟動方法還是調用了spring的run方法,只是在這個方法的前后又做了一些啟動的事,增強了spring而已。

書歸正傳,讓我們重新回到refresh方法中一步步的解讀。在refresh上面打上一個斷點,一步一步看每一個方法都做了什么事。
spring-IOC核心方法refresh()
高能預警:下面是一段超長的源碼分析,可能引起不適,但是對於技術的提高也是顯著的。

@Override
public void refresh() throws BeansException, IllegalStateException {
// 加鎖,避免 refresh() 啟動和銷毀容器混亂this.startupShutdownMonito該鎖為當前對象。
synchronized (this.startupShutdownMonitor) {

  // 准備工作,記錄下容器的啟動時間、標記“已啟動”狀態、處理配置文件中的占位符
  prepareRefresh();

  // 這步比較關鍵,這步完成后,配置文件就會解析成一個個 Bean 定義,注冊到 BeanFactory 中,
  // 當然,這里說的 Bean 還沒有初始化,只是配置信息都提取出來了,
  // 注冊也只是將這些信息都保存到了注冊中心(說到底核心是一個 beanName-> beanDefinition 的 map)
  **ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();**

  // 設置 BeanFactory 的類加載器,添加幾個 BeanPostProcessor,手動注冊幾個特殊的 bean
  // 這塊待會會展開說
  prepareBeanFactory(beanFactory);

  try {
     // 【這里需要知道 BeanFactoryPostProcessor 這個知識點,Bean 如果實現了此接口,
     // 那么在容器初始化以后,Spring 會負責調用里面的 postProcessBeanFactory 方法。】

     // 這里是提供給子類的擴展點,到這里的時候,所有的 Bean 都加載、注冊完成了,但是都還沒有初始化
     // 具體的子類可以在這步的時候添加一些特殊的 BeanFactoryPostProcessor 的實現類或做點什么事
     postProcessBeanFactory(beanFactory);
     // 調用 BeanFactoryPostProcessor 各個實現類的 postProcessBeanFactory(factory) 方法
     invokeBeanFactoryPostProcessors(beanFactory);

     // 注冊 BeanPostProcessor 的實現類,注意看和 BeanFactoryPostProcessor 的區別
     // 此接口兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
     // 兩個方法分別在 Bean 初始化之前和初始化之后得到執行。注意,到這里 Bean 還沒初始化
     registerBeanPostProcessors(beanFactory);

     // 國際化
     initMessageSource();

     // 初始化當前 ApplicationContext 的事件廣播器
     initApplicationEventMulticaster();

     // 從方法名就可以知道,典型的模板方法(鈎子方法),
     // 具體的子類可以在這里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
     onRefresh();

     // 注冊事件監聽器,監聽器需要實現 ApplicationListener 接口。
     registerListeners();

     // 初始化所有的 singleton beans
     //(lazy-init 的除外)
     finishBeanFactoryInitialization(beanFactory);

     // 最后,廣播事件,ApplicationContext 初始化完成
     finishRefresh();
  }

     // Destroy already created singletons to avoid dangling resources.
     // 銷毀已經初始化的 singleton 的 Beans,以免有些 bean 會一直占用資源
     destroyBeans();

     // 把異常往外拋
     throw ex;
  }

  finally {
     // Reset common introspection caches in Spring's core, since we
     // 重置緩存
     resetCommonCaches();
  }

}
}

以上就是refresh()方法概述,如果全部展開來講的話會很長很長,接下來會分很多文章來解讀每一個方法的源碼,但是讀者要對它的所有方法做到心中有數。

spring與其他框架的整合,都蘊含在這些方面中,充分利用了spring的擴展性。

總結

在花了一天時間后,這篇文章終於算是基本寫完了,應該透過現象看本質,去理解 Spring 寫得好的地方,去理解它的設計思想。

充分解讀spring代碼量真的比較大,分支旁路眾多。以后會逐步拆解它的每一個問題,敬請期待吧。


免責聲明!

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



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