最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

12-Spring初級(jí)容器初始化:bean的各種子標(biāo)簽解析

2023-06-14 12:28 作者:儒猿課堂  | 我要投稿

開篇

上一節(jié),我們了解了Spring是如何解析bean標(biāo)簽上各種各樣的屬性的,然后將解析到的屬性值設(shè)置到BeanDefinition中。

bean標(biāo)簽中,除了屬性之外當(dāng)然還包括各種各樣的子標(biāo)簽,比如property標(biāo)簽、constructor-arg標(biāo)簽等,接下來(lái),我們就來(lái)看下這些子標(biāo)簽是如何解析的吧,這一節(jié)主要包括以下幾個(gè)部分:

1.先來(lái)看下Spring中的各種標(biāo)簽是在哪里開始解析的

2.然后我們通過(guò)一個(gè)案例使用下標(biāo)簽constructor-arg

3.接下來(lái)看下constructor-arg標(biāo)簽是如何解析的

4.最后再來(lái)看下property標(biāo)簽又是如何將解析的


子標(biāo)簽:meta、lookup-method和replaced-method


我們從上一節(jié)課看到的位置,繼續(xù)來(lái)分析下:

可以看到,bean標(biāo)簽的解析現(xiàn)在就差這些子標(biāo)簽元素element的解析了,首先,我們看到的是解析子標(biāo)簽meta、lookup-method和replaced-method標(biāo)簽。

我們先來(lái)看下meta子標(biāo)簽是如何解析的:

可以看到解析的過(guò)程也是非常簡(jiǎn)單,就是從bean標(biāo)簽下遍歷獲取meta標(biāo)簽,然后將解析到屬性key和屬性value的值封裝到BeanMetadataAtrribute中。

最后將BeanMetadataAtrribute記錄到BeanMetadataAttributeAccessor中,BeanMetadataAtrribute和BeanMetadataAttributeAccessor,我們可以理解為是Bean封裝屬性和訪問(wèn)屬性的底層類。


lookup-method和replaced-method標(biāo)簽的解析也是類似:

正如我們看到的一樣,meta、lookup-method和replaced-method標(biāo)簽的解析過(guò)程也就這樣,可能有些同學(xué)都不太明白這幾個(gè)子標(biāo)簽到底有什么用,其實(shí),這幾個(gè)標(biāo)簽我們?cè)谌粘i_發(fā)中確實(shí)也幾乎都用不到,所以,我們簡(jiǎn)單看下就行了。

相比于標(biāo)簽meta、lookup-method和replaced-method而言,constructor-arg標(biāo)簽和property標(biāo)簽在工作中用到的概率還會(huì)更大一些,接下來(lái),我們重點(diǎn)來(lái)看下這兩個(gè)標(biāo)簽是如何解析的。


constructor-arg標(biāo)簽的使用


我們先來(lái)簡(jiǎn)單看一下constructor-arg標(biāo)簽是如何使用的,首先,我們寫一個(gè)簡(jiǎn)單的java類,還是以Student類舉例:

可以看到,Student類非常的簡(jiǎn)單,包括一個(gè)String類型的變量name,和一個(gè)int類型的變量age,另外,還添加了一個(gè)包含name和age參數(shù)的構(gòu)造方法。

而constructor-arg標(biāo)簽的功能,就是在Spring在創(chuàng)建bean的時(shí)候,給bean的構(gòu)造方法傳入?yún)?shù)。


接下來(lái),我們?cè)赼pplicationContext.xml中配置下Student類:

可以看到,在bean標(biāo)簽下我們添加了constructor-arg標(biāo)簽,標(biāo)簽中的屬性就是構(gòu)造方法中的參數(shù)名稱,而value標(biāo)簽配置的為參數(shù)的值,可以看到我們配置了兩個(gè)constructor-arg標(biāo)簽,對(duì)應(yīng)構(gòu)造方法中的兩個(gè)參數(shù)。

其實(shí),constructor-arg標(biāo)簽也支持我們按照參數(shù)index,也就是參數(shù)位置來(lái)指定參數(shù)的值:

可以看到,在constructor-arg標(biāo)簽中,因?yàn)閕ndex屬性是從0作為起始下標(biāo)的,index為0表示第一個(gè)參數(shù)name,index為1為第二個(gè)參數(shù)age。

最后,我們?cè)偻ㄟ^(guò)代碼來(lái)測(cè)試下:

運(yùn)行一下代碼,看下效果:

可以看到,構(gòu)造方法的參數(shù)name和age的值,成功通過(guò)constructor-arg標(biāo)簽傳入,constructor-arg標(biāo)簽的使用無(wú)非也就是這樣,接下來(lái),我們?cè)賮?lái)針對(duì)性的看下Spring是如何解析constructor-arg標(biāo)簽的吧。


constructor-arg標(biāo)簽的解析

接下來(lái),我們?cè)倩氐街胺治龅牡胤?

首先,我們到方法parseConstructorArgElements中看下constructor-arg標(biāo)簽是如何解析的:

可以看到,先從bean標(biāo)簽下獲取所有的子節(jié)點(diǎn),然后找到名稱為constructor-arg的標(biāo)簽,再調(diào)用方法parseConstructorArgElement進(jìn)一步解析。


我們跟進(jìn)到方法parseConstructorArgElement中看下:

可以看到方法中的東西還是蠻多的,一眼看過(guò)去可能暈,但是,仔細(xì)看了下發(fā)現(xiàn)無(wú)非也做了幾件事而已,首先將constructor-arg標(biāo)簽中的屬性index、type和name的值都解析出來(lái)。

接著可以看到,首先會(huì)判斷屬性indexAttr屬性是否存在,然后因?yàn)槲覀儎偛旁诎咐幸部吹搅?,在constructor-arg標(biāo)簽中,要么使用index屬性來(lái)配置參數(shù),要么就是用name屬性來(lái)配置參數(shù),所以,根據(jù)是否配置了indexAttr屬性,我們可以看到出現(xiàn) 了兩個(gè)分支。

在這兩個(gè)分支中分別有對(duì)應(yīng)的解析方式,且最終解析出來(lái)的結(jié)果和我們之前分析的一樣,都封裝在了BeanDefinition中。


constructor-arg標(biāo)簽屬性的解析


在方法parseConstructorArgElement中的兩個(gè)分支中,有一個(gè)相同的方法也就是parsePropertyValue,它就是用來(lái)解析constructor-arg標(biāo)簽下的所有子標(biāo)簽和屬性的。

在xml的constructor-arg標(biāo)簽下,可能會(huì)配置各種各樣的屬性值,除了剛才案例中看到的name、index屬性以及value標(biāo)簽之外,還有其他數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)的子標(biāo)簽,如array標(biāo)簽、list標(biāo)簽、set標(biāo)簽、map標(biāo)簽、props標(biāo)簽等,這些屬性標(biāo)簽都可能在constructor-arg標(biāo)簽下,為什么呢?

因?yàn)橐粋€(gè)bean的構(gòu)造方法的參數(shù)類型是多種多樣的,bean構(gòu)造方法中參數(shù)類型為L(zhǎng)ist、Set、Map等都是合情合理且大概率可能會(huì)出現(xiàn)的,Spring對(duì)這些情況都會(huì)極盡考慮,所以在方法parsePropertyValue中會(huì)依次去解析各種各樣的子標(biāo)簽的值。

那Spring具體是如何解析的呢,我們就要到方法parsePropertyValue中看下了:

關(guān)于標(biāo)簽解析這部分的代碼,可以看到,一方面細(xì)節(jié)確實(shí)是太多了,容易讓人頭暈,我們快速過(guò)一遍把握那些關(guān)鍵的點(diǎn)和主流程就可以了。


在parsePropertyValue方法中,首先是獲取constructor-arg標(biāo)簽下的所有子節(jié)點(diǎn)nl,然后在遍歷這些子節(jié)點(diǎn)時(shí),將description和meta標(biāo)簽剔除掉不處理。

一旦發(fā)現(xiàn)有這兩個(gè)類型之外的標(biāo)簽存在時(shí),就記錄到子標(biāo)簽元素subElement中,準(zhǔn)備進(jìn)一步的解析,當(dāng)然這里subElement指的就是我們剛才提到的array標(biāo)簽、list標(biāo)簽、set標(biāo)簽等子標(biāo)簽。


我們繼續(xù)看下去:

可以看到,接下來(lái)開始判斷在constructor-arg標(biāo)簽中,是否配置了屬性ref和屬性value的值。

屬性ref和value我們都比較熟悉,ref是引用另外一個(gè)bean依賴的,而value是配置具體的值的,兩者只能同時(shí)出現(xiàn)其中一個(gè),ref屬性和value屬性在使用時(shí)只能二選一,當(dāng)然,我們?cè)诖a中也看到了如果兩者同時(shí)存在就會(huì)報(bào)錯(cuò)提示。

然后開始對(duì)ref屬性和value屬性分別進(jìn)行解析處理,將解析到的屬性值封裝到BeanDefinition中,但是,如果既沒有配置ref屬性,也沒有配置value屬性,甚至還沒有配置子標(biāo)簽的話,這是不允許的,在最后的一個(gè)else分支中,我們也看到了會(huì)報(bào)錯(cuò)。

但是,如果constructor-arg標(biāo)簽配置了子標(biāo)簽的話,也就是我們剛才記錄的subElement不為空,就會(huì)調(diào)用方法parsePropertySubElement進(jìn)行進(jìn)一步的解析子標(biāo)簽元素subElement。

很顯然,這里才是解析子標(biāo)簽的關(guān)鍵,我們進(jìn)去看下:

可以看到,在方法parsePropertySubElement中又調(diào)用了一個(gè)重載方法parsePropertySubElement,我們繼續(xù)進(jìn)去看下:

終于,我們看到了在方法parsePropertySubElement在解析各種各樣的標(biāo)簽,同時(shí),Spring考慮子標(biāo)簽的周全程度,也遠(yuǎn)超乎我們的想象。


包括ref標(biāo)簽、idref標(biāo)簽、value標(biāo)簽、null標(biāo)簽等,當(dāng)然,我們剛才提到的array標(biāo)簽、list標(biāo)簽、set標(biāo)簽、map標(biāo)簽、props標(biāo)簽也都在解析的范圍之內(nèi),具體怎么解析,其實(shí)相關(guān)的API調(diào)用也大差不差,如果沒有一些特定的需求的話,我們看到這個(gè)程度也就差不多了。


property標(biāo)簽的解析


回到之前解析constructor-arg標(biāo)簽位置:

最后,再來(lái)看下property標(biāo)簽是如何解析的,我們到parsePropertyElements方法中看下:

可以看到,和之前解析constructor-arg標(biāo)簽一樣,先獲取bean標(biāo)簽下的所有子標(biāo)簽,然后從這些子標(biāo)簽中找到property標(biāo)簽進(jìn)行解析。


我們?cè)俚絧arsePropertyElement方法中看下:

可以看到,property標(biāo)簽的解析理解起來(lái)就比較簡(jiǎn)單了。

首先獲取property標(biāo)簽中的name屬性的值,如果發(fā)現(xiàn)之前已經(jīng)解析過(guò)相同名稱的property標(biāo)簽是會(huì)報(bào)錯(cuò)的,也就是說(shuō)在同一個(gè)bean標(biāo)簽中,是不允許存在相同名稱的property標(biāo)簽的。


然后,我們可以看到調(diào)用了方法parsePropertyValue方法:

方法parsePropertyValue我們剛才已經(jīng)分析過(guò)了,其實(shí)就是在解析各種各樣的子標(biāo)簽而已。

然后可以看到,會(huì)將解析到的結(jié)果封裝為PropertyValue,再將PropertyValue添加到BeanDefinition相應(yīng)的數(shù)據(jù)結(jié)構(gòu)中。


總的來(lái)說(shuō),標(biāo)簽的解析過(guò)程雖然細(xì)節(jié)非常的多,當(dāng)然,我們也沒必要強(qiáng)迫自己記住每個(gè)環(huán)節(jié),了解它解析了哪些東西就差不多了,如果哪天需要深入的分析某個(gè)標(biāo)簽的解析,我們也可以回過(guò)頭來(lái)針對(duì)性的研究。

不管怎么樣,我們現(xiàn)在已經(jīng)了解了在xml配置文件中那些讓人眼花繚亂的標(biāo)簽配置,其實(shí)在Spring源碼中都是有實(shí)實(shí)在在代碼解析的。


總結(jié)


好了,今天的知識(shí)點(diǎn),我們就講到這里了,我們來(lái)總結(jié)一下吧。


一張圖來(lái)梳理下當(dāng)前的流程:

這一節(jié),我們看了下bean標(biāo)簽中的各種子標(biāo)簽的解析,而且我們發(fā)現(xiàn)光是標(biāo)簽中的屬性解析,代碼量就恐怖的嚇人,但是不管怎么樣,我們也算是看到這些標(biāo)簽在哪里解析的了,并且解析得到的信息也都是封裝在BeanDefinition中的。

接下來(lái),就差最后一步了,也就是說(shuō)我們千辛萬(wàn)苦將bean標(biāo)簽的各種屬性、各種子標(biāo)簽的信息都封裝到了BeanDefinition之后,BeanDefinition又是如何注冊(cè)到Spring容器中的呢,下一節(jié)我們來(lái)揭曉這塊內(nèi)容。


12-Spring初級(jí)容器初始化:bean的各種子標(biāo)簽解析的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
巫溪县| 永昌县| 广饶县| 鄂托克旗| 台南市| 武川县| 大冶市| 土默特右旗| 县级市| 长兴县| 永嘉县| 苍山县| 邻水| 山西省| 扬中市| 连山| 酒泉市| 山西省| 灌阳县| 福清市| 嘉荫县| 微博| 五河县| 南皮县| 连江县| 泊头市| 内丘县| 乌兰浩特市| 溆浦县| 晋中市| 高密市| 磐安县| 河曲县| 五常市| 凌源市| 龙州县| 兴仁县| 云霄县| 定西市| 获嘉县| 延寿县|