今天來梳理下
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
發生的地方
。
原文連結:https://www。tuicool。com/articles/m6NRzeZ