Spring IOC原理

說到spring不得不提其兩大特性IOC、AOP输钩,本文主要介紹結(jié)合代碼看下spring Ioc相關(guān)原理床玻,閱讀源碼如果只是為了看源碼效率就會很低,還是要有一定的目的性屑柔,我們結(jié)合著以下的問題去源碼中找答案黍特。本篇文章為《圖靈學(xué)院》課程筆記

  • Bean工廠是如何產(chǎn)生Bean的
  • Bean的依賴關(guān)系是由誰來解決的
  • Bean工廠和應(yīng)用上下文的區(qū)別

如下圖spring Ioc的整體架構(gòu)圖中可以看出,Spring啟動時讀取bean配置信息锯蛀,并在spring中生成一份相應(yīng)bean配置注冊表灭衷,然后會根據(jù)注冊表實例化Bean,并且裝配好bean 之間的依賴關(guān)系旁涤,為上層應(yīng)用提供bean實例翔曲,其中bean的緩存池是通過hashmap實現(xiàn)的

image

bean的構(gòu)建過程

spring.xml中保存了Bean的描述配置,BeanFactory讀取這些配置然后生成bean劈愚,這是我們對ioc原理的一般理解瞳遍,深入思考還會有更多問題產(chǎn)生

  • 哪個java對象承載了配置信息里的內(nèi)容
  • 這些承載對象是讀取配置文件并裝載的
  • 這些裝載對象又保存在哪里

BeanDefinition(Bean定義)

ioc 實現(xiàn)中 我們在xml 中描述的Bean信息最后 都將保存至BeanDefinition (定義)對象中,其中xml bean 與BeanDefinition 程一對一的關(guān)系菌羽。xml bean中設(shè)置的屬性最后都會體現(xiàn)在BeanDefinition中

image

由此可見掠械,xml bean中設(shè)置的屬性最后都會體現(xiàn)在BeanDefinition中。如:

**XML-bean ** BeanDefinition
class beanClassName
scope scope
lazy-init lazyInit
constructor-arg ConstructorArgument
property MutablePropertyValues
factory-method factoryMethodName
destroy-method AbstractBeanDefinition.destroyMethodName
init-method AbstractBeanDefinition.initMethodName
autowire AbstractBeanDefinition.autowireMode
id
name

BeanDefinition 屬性結(jié)構(gòu)

image

BeanDefinitionRegistry(Bean注冊器)

在上表中我們并沒有看到 xml bean 中的 id 和name屬性沒有體現(xiàn)在定義中注祖,原因是ID 其作為當(dāng)前Bean的存儲key注冊到了BeanDefinitionRegistry 注冊器中猾蒂。name 作為別名key 注冊到了 AliasRegistry 注冊中心。其最后都是指向其對應(yīng)的BeanDefinition是晨。

BeanDefinitionRegistry屬性結(jié)構(gòu)

image

BeanDefinitionReader(Bean定義讀榷遣ぁ)

現(xiàn)在我們了解 BeanDefinition 中存儲了Xml Bean信息,而BeanDefinitionRegister 基于ID和name 保存了Bean的定義罩缴。接下要學(xué)習(xí)的是從xml Bean到BeanDefinition 然后在注冊至BeanDefinitionRegister 整個過程蚊逢。

image

上圖中可以看出Bean的定義是由BeanDefinitionReader 從xml 中讀取配置并構(gòu)建出 BeanDefinitionReader,然后在基于別名注冊到BeanDefinitionRegister中层扶。

BeanDefinitionReader結(jié)構(gòu)

image
  • int loadBeanDefinitions(Resource var1)

基于資源加載beanDefinition并注冊到注冊器

  • int loadBeanDefinitions(String var1)

    基于資源路徑加載beanDefinition并注冊大屏注冊器

  • BeanDefinitionRegistry getRegistry()

    獲取注冊器

  • ResourceLoader getResourceLoader()

獲取資源裝載器

基于示例演示BeanDefinitionReader裝載過程

//創(chuàng)建一個簡單注冊器
BeanDefinitionRegistry register = new SimpleBeanDefinitionRegistry();
//創(chuàng)建bean定義讀取器
BeanDefinitionReader reader = new XmlBeanDefinitionReader(register);
// 創(chuàng)建資源讀取器
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
// 獲取資源
Resource xmlResource = resourceLoader.getResource("spring.xml");
// 裝載Bean的定義
reader.loadBeanDefinitions(xmlResource);
// 打印構(gòu)建的Bean 名稱
System.out.println(Arrays.toString(register.getBeanDefinitionNames());

Beanfactory(bean 工廠)

有了Bean的定義就相當(dāng)于有了產(chǎn)品的配方,接下來就是要把這個配方送到工廠進行生產(chǎn)了烙荷。在ioc當(dāng)中Bean的構(gòu)建是由BeanFactory 負責(zé)的镜会。其結(jié)構(gòu)如下:

image

方法說明:

  • getBean(String)
    • 基于ID或name 獲取一個Bean
  • T getBean(Class<T> requiredType)
    • 基于Bean的類別獲取一個Bean(如果出現(xiàn)多個該類的實例,將會報錯终抽。但可以指定 primary=“true” 調(diào)整優(yōu)先級來解決該錯誤 )
  • Object getBean(String name, Object... args)
    • 基于名稱獲取一個Bean稚叹,并覆蓋默認的構(gòu)造參數(shù)
  • boolean isTypeMatch(String name, Class<?> typeToMatch)
    • 指定Bean與指定Class 是否匹配

以上方法中重點要關(guān)注getBean,當(dāng)用戶調(diào)用getBean的時候就會觸發(fā) Bean的創(chuàng)建動作拿诸,其是如何創(chuàng)建的呢扒袖?

演示基本BeanFactory獲取一個Bean

#創(chuàng)建Bean堆棧
// 其反射實例化Bean
java.lang.reflect.Constructor.newInstance(Unknown Source:-1)
BeanUtils.instantiateClass()
//基于實例化策略 實例化Bean
SimpleInstantiationStrategy.instantiate()
AbstractAutowireCapableBeanFactory.instantiateBean()
// 執(zhí)行Bean的實例化方法
AbstractAutowireCapableBeanFactory.createBeanInstance()
AbstractAutowireCapableBeanFactory.doCreateBean()
// 執(zhí)行Bean的創(chuàng)建
AbstractAutowireCapableBeanFactory.createBean()
// 緩存中沒有,調(diào)用指定Bean工廠創(chuàng)建Bean
AbstractBeanFactory$1.getObject()
// 從單例注冊中心獲取Bean緩存
DefaultSingletonBeanRegistry.getSingleton()
AbstractBeanFactory.doGetBean()
// 獲取Bean
AbstractBeanFactory.getBean()
// 調(diào)用的客戶類
com.tuling.spring.BeanFactoryExample.main()

Bean創(chuàng)建時序圖:

image

從調(diào)用過程可以總結(jié)出以下幾點:

  1. 調(diào)用BeanFactory.getBean() 會觸發(fā)Bean的實例化亩码。
  2. DefaultSingletonBeanRegistry 中緩存了單例Bean
  3. Bean的創(chuàng)建與初始化是由AbstractAutowireCapableBeanFactory 完成的季率。

BeanFactory 與 ApplicationContext區(qū)別

BeanFactory 看上去可以去做IOC當(dāng)中的大部分事情,為什么還要去定義一個ApplicationContext 呢描沟?
ApplicationContext 結(jié)構(gòu)圖

image

從圖中可以看到 ApplicationContext 它由BeanFactory接口派生而來飒泻,因而提供了BeanFactory所有的功能。除此之外context包還提供了以下的功能:

  1. MessageSource, 提供國際化的消息訪問
  2. 資源訪問吏廉,如URL和文件
  3. 事件傳播泞遗,實現(xiàn)了ApplicationListener接口的bean
  4. 載入多個(有繼承關(guān)系)上下文 ,使得每一個上下文都專注于一個特定的層次席覆,比如應(yīng)用的web層

原文地址

http://cbaj.gitee.io/blog/2020/08/05/Spring%7CIOC%E5%8E%9F%E7%90%86/#more

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末史辙,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子佩伤,更是在濱河造成了極大的恐慌聊倔,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件生巡,死亡現(xiàn)場離奇詭異耙蔑,居然都是意外死亡,警方通過查閱死者的電腦和手機孤荣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門甸陌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盐股,你說我怎么就攤上這事钱豁。” “怎么了遂庄?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵寥院,是天一觀的道長。 經(jīng)常有香客問我涛目,道長秸谢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任霹肝,我火速辦了婚禮估蹄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沫换。我一直安慰自己臭蚁,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布讯赏。 她就那樣靜靜地躺著垮兑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪漱挎。 梳的紋絲不亂的頭發(fā)上系枪,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天,我揣著相機與錄音磕谅,去河邊找鬼私爷。 笑死,一個胖子當(dāng)著我的面吹牛膊夹,可吹牛的內(nèi)容都是我干的衬浑。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼放刨,長吁一口氣:“原來是場噩夢啊……” “哼工秩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起进统,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤拓诸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后麻昼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奠支,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年抚芦,在試婚紗的時候發(fā)現(xiàn)自己被綠了倍谜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡叉抡,死狀恐怖尔崔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情褥民,我是刑警寧澤季春,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站消返,受9級特大地震影響载弄,放射性物質(zhì)發(fā)生泄漏耘拇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一宇攻、第九天 我趴在偏房一處隱蔽的房頂上張望惫叛。 院中可真熱鬧,春花似錦逞刷、人聲如沸嘉涌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仑最。三九已至,卻和暖如春帆喇,著一層夾襖步出監(jiān)牢的瞬間警医,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工番枚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留法严,地道東北人。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓葫笼,卻偏偏與公主長得像深啤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子路星,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361