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