16 張圖解鎖 Spring 的整體脈絡
今天來梳理下 Spring 的整體脈絡啦,為后面的文章做個鋪墊~
話說咱們一直都在用這個 Spring ,你們對它的感受是啥呀?還是說說不出來 哈哈
4ye 的感覺也是零零散散的,而且印象中一直都在用 Springboot ,不用再配置一堆東西呀,管理依賴啥的,方便太多了。
所以借此機會簡單梳理下其中的一些脈絡,這樣去看源碼就有條理多啦,更能知道一些擴展點的使用等:stuck_out_tongue_closed_eyes:
目錄
本文會先大概介紹下這些知識點 :point_down:
印象中的 Spring
腦海中有這么一條公式:
:point_right: IOC = 工廠模式 + XML + 反射
:point_right: 而 DI , AOP , 事務 等也都在 XML 中很直觀的表現出來
雖然我們現在大部分用這個注解來代替,但是原理還是基本一樣的:pig2:
注解使用起來很方便,但是學習的話,還是建議先通過這個 XML ,畢竟結構性的文檔,有層次感,可以留下更深的印象~ :smile:
小小Spring
把 Spring 濃縮一下,就有了這么一點小東西:pig2:
想了下,我們用 Spring ,其中最主要的一點,就是用它來幫我們管理,創建這個 Bean 。
那么先從源頭看起 —— Bean 從哪來 (@_@;)
Bean 解析流程
如圖所示,就是通過 解析器 ,對我們的 XML 文件或者注解進行解析,最后將這些信息封裝在 BeanDefinition 類中,并通過 BeanDefinitionRegistry 接口將這些信息 注冊 起來,放在 beanDefinitionMap 變量中, key : beanName , value :BeanDefinition
簡單看看 BeanDefinition 中的屬性叭
BeanDefinition
-
beanClass : bean 的類型 ,實例化時用的 :pig2:
-
scope : 作用范圍有 singleton,prototype
-
isLazy : 懶加載 ,true 的話 會在 getBean 時生成,而且 scope 的 prototype 無效,false 在 Spring 啟動過程中直接生成
-
initMethodName : 初始化方法,當然是初始化時調用:pig2:
-
primary : 主要的,有多個 Bean 時使用它
-
dependsOn : 依賴的Bean,必須等依賴Bean 創建好才可以創建
PS: @Component ,@Bean , 都會被解析成 BeanDefinition
反射
有了原料后呢, 咱 們再來看看這個 工廠 BeanFactory
先簡單想一想這個工廠要怎么創建這個 Bean 呢?
沒錯,肯定就是這個 反射 啦 :smile:
那么,結合我們從原料中獲取的重要屬性之一的 beanClass ,我們可以畫出這么一張圖 :point_down:
那么我們再來看看這個 BeanFactory 叭 :smile:
BeanFactory
先來看看 作為IOC 容器的 根接口 的 BeanFactory 提供了什么方法吧:point_down:
主要是這個 getBean 方法,以及 別名獲取 , 類型獲取 方法和其他一些判斷方法如 : 單例 , 多例 , 類型匹配 , 包含bean
我們來簡單看看它的子接口都有哪些叭~:smile:
這里分享個小技巧叭:pig2:
看源碼的時候,一般就直接看這個 默認 接口 如這里的 DefaultListableBeanFactory
基本上看個類名就知道大概作用了,那么先對號入座下:point_down:
ListableBeanFactory
:point_right: 遍歷 bean
HierarchicalBeanFactory
:point_right: 提供 父子關系,可以獲取上一級的 BeanFactory
ConfigurableBeanFactory
:point_right: 實現了 SingletonBeanRegistry ,主要是 單例Bean的注冊,生成
AutowireCapableBeanFactory
:point_right: 和自動裝配有關的
AbstractBeanFactory
:point_right: 單例緩存,以及 FactoryBean 相關的
ConfigurableListableBeanFactory
:point_right: 預實例化單例Bean,分析,修改 BeanDefinition
AbstractAutowireCapableBeanFactory
:point_right: 創建 Bean ,屬性注入,實例化,調用初始化方法 等等
DefaultListableBeanFactory
:point_right: 支持單例Bean ,Bean別名 ,父子BeanFactory,Bean 類型轉化 ,Bean 后置處理,FactoryBean,自動裝配等
是不是非常豐富 :smile:
FactoryBean
FactoryBean ,它本身就是個 Bean,算是小工廠 ,歸 BeanFactory 這個大工廠管理的。
可以看到它就只有三個方法
-
getObject() 獲取對象
-
isSingleton() 單例對象
-
getObjectType() 返回的是 Bean 對象的類型
相比大工廠 BeanFactory 少了特別多東西,沒有嚴格的 Bean 生命周期流程
在 :point_right: 《三分鐘快速了解Spring中的工廠模式》 一文中有介紹到 :smile:
FacotryBean 對象本身也是一個Bean,是一個小工廠,可以生產另外的 Bean
BeanFactory 是 Spring 容器的根接口,是大工廠,生產各種各樣的Bean
beanName 就是正常對象
“&”+beanName , 獲取的是實現了該接口的 FacotryBean 工廠對象
大致如下 :point_down:
ApplicationContext
我們再來看看這個 ApplicationContext
可以看到它擴展了很多功能,除了 BeanFactory ,它還可以 創建 , 獲取 Bean ,以及處理 國際化 , 事件 , 獲取資源 等
-
EnvironmentCapable 獲取 環境變量 的功能,可以獲取到 操作系統變量 和 JVM 環境變量
-
ListableBeanFactory 獲取所有 BeanNames,判斷某個 BeanName 是否存在 BeanDefinition 對象,統計 BeanDefinition 對象,獲取某個類型對應的所有 beanNames 等功能
-
HierarchicalBeanFactory 獲取父 BeanFactory ,判斷某個 name 是否存在 bean 對象的功能
-
MessageSource 國際化功能 ,獲取某個國際化資源
-
ApplicationEventPublisher 事件發布功能 (重點)
-
ResourcePatternResolver 加載,獲取資源的功能 ,這里的資源可能是文件,圖片 等某個URL資源都可以
還有這三個重要的類:point_down:,就不一一介紹先啦:smile:
-
ClassPathXmlApplicationContext
-
AnnotationConfigApplicationContext
-
FileSystemXmlApplicationContext
趕緊來看看這個核心叭!
IOC 容器
當然,這時候出場的肯定是 IOC 啦。
我們都知道 IOC 是 控制反轉 ,但是別忘了 容器 這個詞,比如 **容器的根接口 **BeanFactory , 容器的實現 :point_down:
-
ClassPathXmlApplicationContext
-
AnnotationConfigApplicationContext
-
FileSystemXmlApplicationContext
同時我們要注意這里無處不在的 后置處理器 xxxPostProcessor :pig:
這個是 Spring 中擴展性強的原因了!
我們可以在各個過程中合理應用這些 PostProcessor 來擴展,或者修改 Bean 定義信息等等
可以看到在這個容器中,完成了 Bean 的初始化,而這個過程還有很多細節 ,請往下看看:point_down:
DI 到時寫 屬性填充 時再介紹:pig:
BeanFactory 后置處理器
作為 IOC 容器根接口的 BeanFactory ,有著非常高的擴展性,比如最開始獲取原料 BeanDefinition 時,就出現了兩個針對 BeanFactory 工廠的后置處理器 :point_down:
BeanDefinitionRegistryPostProcessor
通過該接口,我們可以自己掌控我們的 原料 ,通過 BeanDefinitionRegistry 接口去 新增 , 刪除 , 獲取 我們這個 BeanDefinition
BeanFactoryPostProcessor
通過該接口,可以在 實例化對象前 ,對 BeanDefinition 進行修改 , 凍結 , 預實例化單例Bean 等
經過上面層層阻礙后,我們最終會來到目標方法 getBean ,將原料投入生產,最終獲取一個個 Bean 對象出來
那么隨之而來的就是這個 Bean 的生命周期啦 :smile:
Bean 生命周期
Bean 的創建和管理有 標準化的流程 !
這里在我們的工廠 BeanFactory 中寫得很清楚 :point_down:
總共 14 個步驟,是不是一下子就清晰多了:smile:
在看這部分的源碼時,要多注意兩個英文單詞 :stuck_out_tongue_closed_eyes:
-
實例化:point_right: Instantiation
-
初始化:point_right: Initialization
ps: 別看快搞錯了 哈哈:stuck_out_tongue_closed_eyes:
仔細閱讀上面這14個步驟,會發現前面 8 個都是 Aware 接口,而他們的作用也很簡單,就是獲取 xxAware 這個單詞的前綴 xx :smile:
比如我們在上文 :point_right: 《三分鐘快速上手Spring事件機制》 中提到的事件發布器 ApplicationEventPublisher ,只要你實現了 ApplicationEventPublisherAware 接口,就可以 獲取 事件發布器 ApplicationEventPublisher !
Bean 后置處理器
在實例化 和 初始化流程中,把這個Bean 的后置處理器 BeanPostProcessor 安排上,就得到下圖啦 :point_down:
這里留意下 實例化 有擴展點 InstantiationAwareBeanPostProcessor , 初始化 擴展點 BeanPostProcessor 就非常多啦,我們主要來關注下這個 AOP
AOP
那么 AOP 是在哪個步驟代理對象的呢?:point_down:
可以在 AbstractAutoProxyCreator 類中看到 :point_down:
總結
本文就先介紹到這里啦:pig2:
主要介紹了 Spring 里面的這些脈絡,方便小伙伴們對它有個整體的印象先~
再介紹其中的一些擴展點,比如從源材料的 BeanFactoryPostprocessor ,到產物 Bean 的 BeanPostprocessor 。
實例化,初始化的順序,Bean的生命周期,以及 BeanFactory 及子類擴展的功能,再到 ApplicationContext 的功能。
還有這個核心機制: 工廠+XML+反射 ,以及引出下文要說的 AOP 發生的地方 。