引言
“ 目前,在以Java語言主導的項目中,我們會使用各種各樣的框架來快速搭建應用,尤其在Java web項目中,我們會經常見到Spring的身影,大部分人只知道怎麼使用它,但是不知道它真正的運行原理。本篇文章就來揭祕一下Spring框架的整體面容”
我想很多同學和我一樣,在學習閱讀源碼前都或多或少有些疑問,在這裏簡單總結一下常見的問題。
看源碼既費精力又無聊有啥用呢?
看完源碼對我到底有哪些好處呢?
源碼從那開始讀?怎麼讀?
Spring容器啓動整體流程?
帶着這幾個問題,來看看閱讀源碼是如何讓我們受益的?
01
—
讀源碼有啥用?
從我自己的角度理解,工作一段時間以後,還是在做着重複的CRUD操作,當遇到一些比較怪異的線上故障的時候,不能像別人一樣快速定位問題,總是沒有頭緒,眉毛鬍子一把抓;遇到這樣的問題多數是因爲對運行的系統理解的深度不夠,只知其表。所以針對這種情況,我覺得應該深入底層去理解其背後的運行原理是至關重要的。
02
—
讀源碼的收益是啥?
從我自己現在的體會來講,主要有如下:
對系統整體的運行輪廓有一個比較清晰的認知,寫代碼更加遊刃有餘
學習一些框架優秀的設計思想
爲跳槽做一些知識儲備
03
—
源碼從那開始讀?
這個就比較簡單了,以Spring源碼爲例。首先下載好源碼包,寫一些簡單的測試用例,利用強大的debug功能調試起來,屢試不爽。在後面的源碼閱讀都會採用這種辦法來“偷窺”其真容
04
—
Spring的IoC“輪廓”?
解決了我們的基本困惑之後,進去我們的正題,Spring到底是怎麼運行起來的呢?在解答這個問題之前,我們先從宏觀上看下Spring的“輪廓”,防止在讀源碼的時候不會一頭扎進去出不來,導致很快就放棄了自己當初信誓旦旦立下的flag。我以Spring5.0.7爲例展開。大家可以選擇一個版本去閱讀,整體流程上不會有太大的出入。下面附上我整理的Spring的流程圖(畫的不好,還請見諒,文末附上搭建測試工程用到的核心依賴配置文件)
對於Spring啓動及bean實例化的整體流程如上圖,大家先做一個簡單的瞭解。每一步的工作也寫明瞭,需要注意的是,比較重要的四步我使用了紅色的橢圓標明瞭。
Spring的IoC全名是 Inversion of Control,即控制反轉,大白話來講就是由原來我們自己親手new對象的工作交給了Spring來幫我們做了,我們只在需要指定對象的時候找Spring容器去拿就好了,就這麼簡單。
比較重要的幾個方法我在這裏在列一下:
obtainFreshBeanFactory(),其作用是創建Spring容器的工廠,並解析配置文件構建相應的BeanDefinition對象(BeanDefinition會貫穿整個源碼閱讀,在這裏我們把它就叫做Bean定義,bean對象就是用它來實例化的)
invokeBeanFactoryPostProcessors(),其作用是調用所有實現了BeanFactoryPostProcessor接口或者是BeanDefinitionRegistryPostProcessor子接口的類,簡單理解就是修改BeanDefinition定義的即可
registerBeanPostProcessors(),其作用是將實現了BeanPostProcessor接口的類註冊到Spring容器中,在後面Bean實例初始化前後的時候調用其實現,簡單理解就是要在bean實例初始化前後做一些增加功能即可
finishBeanFactoryInitialization(),其作用是創建所有非懶加載(非懶加載的意思就是提前加載好方便;相對應的是懶加載,就是在要使用的)
總結
本文主要闡明閱讀源碼能給我們帶來哪些收益,以及Spring容器啓動的整體流程概覽。下一篇文章我們將會展開如何debug進入源碼及第一個重要方法obtainFreshBeanFactory()的實現細節。堅持閱讀下去,我會盡自己的努力以最直白的話去闡明Spring的流程。最後歡迎提出意見,共同進步。
附件
maven構建Spring源碼調試工程用到的依賴,持續更新中
<dependencies>
<!-- spring 核心組件中的4個依賴 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<!-- 單元測試Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>