成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一起來(lái)讀Spring源碼吧(一)容器的初始化

libxd / 3102人閱讀

摘要:對(duì)于開發(fā)者來(lái)說,無(wú)疑是最常用也是最基礎(chǔ)的框架之一。概念上的東西還是要提一嘴的用容器來(lái)管理。和是容器的兩種表現(xiàn)形式。定義了簡(jiǎn)單容器的基本功能。抽象出一個(gè)資源類來(lái)表示資源調(diào)用了忽略指定接口的自動(dòng)裝配功能委托解析資源。

對(duì)于Java開發(fā)者來(lái)說,Spring無(wú)疑是最常用也是最基礎(chǔ)的框架之一。(此處省略1w字吹Spring)。相信很多同行跟我一樣,只是停留在會(huì)用的階段,比如用@Component寫一個(gè)組件、用@Autowired注入其他組件等等,但是不知道為什么可以這么做,Spring是怎么實(shí)現(xiàn)的。為了了解這些,我閱讀了《Spring源碼深度解析》,這本書講的很詳細(xì),但是因?yàn)椴襟E多而復(fù)雜容易記混,我就做了一下梳理,先呈現(xiàn)大致流程,但對(duì)每個(gè)步驟進(jìn)行詳細(xì)描述。

概念上的東西還是要提一嘴的:
Spring用IoC容器來(lái)管理Bean。
BeanFactory和ApplicationContext是SpringIoC容器的兩種表現(xiàn)形式。
BeanFactory定義了簡(jiǎn)單IoC容器的基本功能。
ApplicationContext實(shí)現(xiàn)了BeanFactory,且通過繼承MessageSource、ResourceLoader、ApplicationEventPublisher接口,添加了許多高級(jí)容器的特性。

這里以XmlBeanFactory為代表,看容器是怎么工作的。
新建一個(gè)XmlBeanFactory很簡(jiǎn)單,只需要你有一個(gè)符合格式的xml文件,里面用標(biāo)簽設(shè)置你希望被容器加載的Bean:

BeanFactory bf = new XmlBeanFactory(new ClassPathResource("test.xml"))

新建了一個(gè)ClassPathResource資源對(duì)象作為參數(shù)傳入XmlBeanFactory的構(gòu)造函數(shù)。
點(diǎn)進(jìn)XmlBeanFactory類,XmlBeanFactory會(huì)先調(diào)用父類構(gòu)造器,一直跟蹤到AbstractAutowireCapableBeanFactory,會(huì)看到調(diào)用了三次ignoreDependencyInterface用來(lái)忽略給定接口的自動(dòng)裝配功能(后面會(huì)提到);再調(diào)用this.reader.loadBeanDefinitions(Resource),用自己持有的XmlBeanDefinitionReader解析傳入的資源。所以最宏觀的三個(gè)步驟:
1、新建了一個(gè)ClassPathResource資源。抽象出一個(gè)資源類來(lái)表示資源;
2、調(diào)用了ignoreDependencyInterface忽略指定接口的自動(dòng)裝配功能;
3、委托XmlBeanDefinitionReader解析資源。
重點(diǎn)肯定在第三步了,點(diǎn)進(jìn)XmlBeanDefinitionReader,到loadBeanDefinitions(EncodedResource),先從
Resource獲取InputStream構(gòu)造成InputSource,作為參數(shù)調(diào)用doLoadBeanDefinitions(InputSource, Resource)開始真正的解析。所以第三步下面是兩個(gè)小步驟:
3.1、從Resource獲取輸入流;
3.2、調(diào)用doLoadBeanDefinitions繼續(xù)解析。
再看doLoadBeanDefinitions方法,主要是兩個(gè)方法,doLoadDocument(inputSource, resource)解析輸入流返回一個(gè)Document對(duì)象;registerBeanDefinitions(doc, resource)繼續(xù)解析Document返回解析的Bean數(shù)量,所以3.2下面是兩個(gè)步驟:
3.2.1、將資源解析成Document對(duì)象(這個(gè)步驟這邊就不展開了,有興自究);
3.2.2、解析Document,提取注冊(cè)Bean。
來(lái)到registerBeanDefinitions方法,這里創(chuàng)建了一個(gè)BeanDefinitionDocumentReader對(duì)象負(fù)責(zé)具體解析(是不是覺得又冒出了不認(rèn)識(shí)的類,框架就是這樣,遵循單一職責(zé)的原則,把一個(gè)集中的邏輯放到其他類中處理),它調(diào)用doRegisterBeanDefinitions(doc.getDocumentElement()),提取Document的root作為參數(shù)繼續(xù)解析,先查找解析profile屬性,將表示環(huán)境的屬性注冊(cè)到Environment;然后遍歷root每個(gè)子節(jié)點(diǎn),如果是默認(rèn)標(biāo)簽,調(diào)用parseDefaultElement進(jìn)行解析;如果是自定義標(biāo)簽,就調(diào)用delegate.parseCustomElement。所以3.2.2下面是這幾個(gè)步驟:
3.2.2.1、創(chuàng)建BeanDefinitionDocumentReader委托解析對(duì)象;
3.2.2.2、解析profile屬性到Environment;
3.2.2.3、遍歷子節(jié)點(diǎn),繼續(xù)解析默認(rèn)標(biāo)簽和自定義標(biāo)簽。
我們這邊主要分析默認(rèn)標(biāo)簽的解析,自定義的有興自究。首先根據(jù)標(biāo)簽類型選擇不同的處理方法,類型分別是import、alias、bean和beans。重點(diǎn)肯定是對(duì)bean標(biāo)簽的解析,進(jìn)入processBeanDefinition方法,我們看到里面先委托BeanDefinitionParserDelegate解析出一個(gè)持有bean信息的BeanDefinitionHolder;如果BeanDefinitionHolder不為空且子節(jié)點(diǎn)下存在自定義標(biāo)簽,再解析它們;然后對(duì)解析完成后的BeanDefinitionHolder進(jìn)行注冊(cè),注冊(cè)過程很簡(jiǎn)單就是將BeanDefinitionHolder持有的beanName和BeanDefinition的鍵值對(duì)、beanName和每個(gè)alias別名的鍵值對(duì)保存在容器中;最后發(fā)出bean已注冊(cè)完成的事件通知,所以這里分為4步:
3.2.2.3.1、委托BeanDefinitionParserDelegate解析返回BeanDefinitionHolder;
3.2.2.3.2、解析存在的自定義標(biāo)簽;
3.2.2.3.3、解析完成后注冊(cè);
3.2.2.3.4、發(fā)出響應(yīng)事件。
到了這里終于開始具體的解析,過程其實(shí)就是先解析出beanName、alias別名,然后把其余各種標(biāo)簽,如class、scope、lazy-init等屬性解析成用于屬性承載的BeanDefinition對(duì)象的成員變量,最后將beanName、alias數(shù)組和BeanDefinition封裝成BeanDefinitionHolder對(duì)象返回。具體各種屬性的功能和規(guī)則這邊就不展開了,有興自究。
對(duì)于import、alias和beans標(biāo)簽,簡(jiǎn)述一下:alias的解析和bean中的alias解析差不多,也是將每一個(gè)別名與beanName以map形式保存;impot可以導(dǎo)入其他配置文件,解析過程就是找到那個(gè)文件然后遞歸進(jìn)行解析;beans就是把多個(gè)bean標(biāo)簽包起來(lái),然后遍歷解析每一個(gè)bean標(biāo)簽。

畫一個(gè)流程圖作為總結(jié):

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/72507.html

相關(guān)文章

  • Spring IOC 容器源碼分析系列文章導(dǎo)

    摘要:本文是容器源碼分析系列文章的第一篇文章,將會(huì)著重介紹的一些使用方法和特性,為后續(xù)的源碼分析文章做鋪墊。我們可以通過這兩個(gè)別名獲取到這個(gè)實(shí)例,比如下面的測(cè)試代碼測(cè)試結(jié)果如下本小節(jié),我們來(lái)了解一下這個(gè)特性。 1. 簡(jiǎn)介 Spring 是一個(gè)輕量級(jí)的企業(yè)級(jí)應(yīng)用開發(fā)框架,于 2004 年由 Rod Johnson 發(fā)布了 1.0 版本。經(jīng)過十幾年的迭代,現(xiàn)在的 Spring 框架已經(jīng)非常成熟了...

    NSFish 評(píng)論0 收藏0
  • 零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)

    摘要:依賴注入是向某個(gè)類或方法注入一個(gè)值,其中所用到的原理就是控制反轉(zhuǎn)。但發(fā)現(xiàn)更多時(shí)間是在調(diào)和的源碼。里面就是從中取出這個(gè),完成控制反轉(zhuǎn)的??刂品崔D(zhuǎn)的優(yōu)點(diǎn)最后來(lái)以我個(gè)人觀點(diǎn)談?wù)効刂品崔D(zhuǎn)的優(yōu)點(diǎn)吧??刂品崔D(zhuǎn)為了降低項(xiàng)目耦合,提高延伸性。 本章開始來(lái)學(xué)習(xí)下Spring的源碼,看看Spring框架最核心、最常用的功能是怎么實(shí)現(xiàn)的。網(wǎng)上介紹Spring,說源碼的文章,大多數(shù)都是生搬硬推,都是直接看來(lái)的...

    wing324 評(píng)論0 收藏0
  • Spring IOC 容器源碼分析 - 循環(huán)依賴解決辦法

    摘要:實(shí)例化時(shí),發(fā)現(xiàn)又依賴于。一些緩存的介紹在進(jìn)行源碼分析前,我們先來(lái)看一組緩存的定義??墒强赐暝创a后,我們似乎仍然不知道這些源碼是如何解決循環(huán)依賴問題的。 1. 簡(jiǎn)介 本文,我們來(lái)看一下 Spring 是如何解決循環(huán)依賴問題的。在本篇文章中,我會(huì)首先向大家介紹一下什么是循環(huán)依賴。然后,進(jìn)入源碼分析階段。為了更好的說明 Spring 解決循環(huán)依賴的辦法,我將會(huì)從獲取 bean 的方法getB...

    aikin 評(píng)論0 收藏0
  • Spring AOP 源碼分析系列文章導(dǎo)

    摘要:在寫完容器源碼分析系列文章中的最后一篇后,沒敢懈怠,趁熱打鐵,花了天時(shí)間閱讀了方面的源碼。從今天開始,我將對(duì)部分的源碼分析系列文章進(jìn)行更新。全稱是,即面向切面的編程,是一種開發(fā)理念。在中,切面只是一個(gè)概念,并沒有一個(gè)具體的接口或類與此對(duì)應(yīng)。 1. 簡(jiǎn)介 前一段時(shí)間,我學(xué)習(xí)了 Spring IOC 容器方面的源碼,并寫了數(shù)篇文章對(duì)此進(jìn)行講解。在寫完 Spring IOC 容器源碼分析系列...

    張春雷 評(píng)論0 收藏0
  • Spring IOC 容器源碼分析 - 獲取單例 bean

    摘要:簡(jiǎn)介為了寫容器源碼分析系列的文章,我特地寫了一篇容器的導(dǎo)讀文章。在做完必要的準(zhǔn)備工作后,從本文開始,正式開始進(jìn)入源碼分析的階段。從緩存中獲取單例。返回以上就是和兩個(gè)方法的分析。 1. 簡(jiǎn)介 為了寫 Spring IOC 容器源碼分析系列的文章,我特地寫了一篇 Spring IOC 容器的導(dǎo)讀文章。在導(dǎo)讀一文中,我介紹了 Spring 的一些特性以及閱讀 Spring 源碼的一些建議。在...

    lufficc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<