日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring IOC BeanDefinition解析

發(fā)布時(shí)間:2025/3/15 javascript 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring IOC BeanDefinition解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Spring IOC BeanDefinition解析

IOC(Inversion of Control)即控制反轉(zhuǎn),是說創(chuàng)建對(duì)象的控制權(quán)進(jìn)行了轉(zhuǎn)移,以前創(chuàng)建對(duì)象的主動(dòng)權(quán)和創(chuàng)建時(shí)機(jī)是由自己把控的,而現(xiàn)在這種權(quán)利轉(zhuǎn)移到Spring IOC容器。許多非凡的應(yīng)用,都是由兩個(gè)或者多個(gè)類通過彼此的合作依賴來實(shí)現(xiàn)業(yè)務(wù)邏輯的,在Spring中,這些依賴關(guān)系可以通過把對(duì)象的依賴注入交給IOC容器來管理,這樣在解耦代碼的同時(shí)提高了代碼的可測(cè)試性。

1.??? 加載bean

加載bean的流程:

(1)???? 封裝資源文件。當(dāng)進(jìn)入XmlBeanDefinitionReader后首先對(duì)參數(shù)Resource使用EncodedResource類進(jìn)行封裝。

(2)???? 獲取輸入流。從Resource中獲取對(duì)應(yīng)的InputStream并構(gòu)造InputSource。

(3)???? 通過構(gòu)造的InputSource實(shí)例和Resource實(shí)例繼續(xù)調(diào)用函數(shù)doLoadBeanDefinitions。

我們來看一下doLoadBeanDefinitions函數(shù)的具體的實(shí)現(xiàn)過程(中間省略了loadBeanDefinitions具體方法的一步):

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {return loadBeanDefinitions(new EncodedResource(resource)); }

繼續(xù)跟進(jìn)代碼,進(jìn)入真正的核心處理部分doLoadBeanDefinitions(inputSource, encodedResource.getResource())

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {try {Document doc = doLoadDocument(inputSource, resource);return registerBeanDefinitions(doc, resource);}catch (BeanDefinitionStoreException ex) {throw ex;}// ……省略異常處理部分}

?

在上面冗長(zhǎng)的代碼中,假如不考慮異常類的代碼,其實(shí)只做了三件事,這三件事的每一件事都必不可少。

(1)???? 獲取對(duì)XML文件的驗(yàn)證模式。

(2)???? 加載XML文件,并得到對(duì)應(yīng)的Document。

(3)???? 根據(jù)返回的Document注冊(cè)bean信息。

2.??? 獲取XML的驗(yàn)證模式

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());}

?2.1驗(yàn)證模式的讀取

了解XML文件的讀者都應(yīng)該知道XML文件的驗(yàn)證模式保證了XML文件的正確性,而比較常用的驗(yàn)證模式有兩種:DTD和XSD。

對(duì)于驗(yàn)證模式,讀者可以自行查閱數(shù)據(jù)了解。

驗(yàn)證模式的讀取方法如下:

protected int getValidationModeForResource(Resource resource) {int validationModeToUse = getValidationMode();if (validationModeToUse != VALIDATION_AUTO) {return validationModeToUse;}int detectedMode = detectValidationMode(resource);if (detectedMode != VALIDATION_AUTO) {return detectedMode;}// Hmm, we didn't get a clear indication... Let's assume XSD,// since apparently no DTD declaration has been found up until// detection stopped (before finding the document's root tag).return VALIDATION_XSD;}

?方法的實(shí)現(xiàn)其實(shí)還是很簡(jiǎn)單的,無非是如果設(shè)定了驗(yàn)證模式則使用設(shè)定的驗(yàn)證模式,否則使用自動(dòng)的驗(yàn)證模式,自檢測(cè)驗(yàn)證模式的功能相對(duì)來說比較簡(jiǎn)單,這里就不再多說了。

3.??? 獲取Document

經(jīng)過了驗(yàn)證模式準(zhǔn)備的步驟就可以進(jìn)行Document加載了,同樣XmlBeanDefinitionReader對(duì)于文檔的讀取并沒有親力親為,而是委托給了DocumentLoader去執(zhí)行,解析代碼如下(DefaultDocumentLoader中)

public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);if (logger.isDebugEnabled()) {logger.debug("Using JAXP provider [" + factory.getClass().getName() + "]");}DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);return builder.parse(inputSource);}

?對(duì)于這部分代碼其實(shí)并沒有太多可以描述的,因?yàn)橥ㄟ^SAX解析XML文檔的套路大致都差不多,Spring在這里并沒有什么特殊的地方,同樣首先創(chuàng)建DocumentBuilderFactory再通過DocumentBuilderFactory創(chuàng)建DocumentBuilder,進(jìn)而解析inputSource來返回Document對(duì)象。

4.??? 解析及注冊(cè)BeanDefinitions

? 把文件轉(zhuǎn)換成Document之后,接下來就可以提取及注冊(cè)bean了。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {//使用DefaultBeanDefinitionDocumentReader實(shí)例化BeanDefinitionDocumentReaderBeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); // 在實(shí)例化BeanDefinitionReader時(shí)候會(huì)將BeanDefinitionRegistry傳入,默認(rèn)使用繼承自DefaultListableBeanFactory的子類// 記錄統(tǒng)計(jì)前BeanDefinition的加載個(gè)數(shù)int countBefore = getRegistry().getBeanDefinitionCount();// 加載及注冊(cè)bean documentReader.registerBeanDefinitions(doc, createReaderContext(resource));// 記錄本次加載的BeanDefinition個(gè)數(shù)return getRegistry().getBeanDefinitionCount() - countBefore;}

?? 進(jìn)入DefaultBeanDefinitionDocumentReader的registerBeanDefinitions方法

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {this.readerContext = readerContext;logger.debug("Loading bean definitions");Element root = doc.getDocumentElement();doRegisterBeanDefinitions(root);}

?下面進(jìn)入核心邏輯的底部doRegisterBeanDefinitions(root)方法

protected void doRegisterBeanDefinitions(Element root) {// 專門處理解析BeanDefinitionParserDelegate parent = this.delegate;this.delegate = createDelegate(getReaderContext(), root, parent);if (this.delegate.isDefaultNamespace(root)) {// 處理profile屬性String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if (StringUtils.hasText(profileSpec)) {String[] specifiedProfiles = StringUtils.tokenizeToStringArray(profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {if (logger.isInfoEnabled()) {logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +"] not matching: " + getReaderContext().getResource());}return;}}}// 解析前處理,留給子類實(shí)現(xiàn) preProcessXml(root);parseBeanDefinitions(root, this.delegate);// 解析后處理,留給子類實(shí)現(xiàn) postProcessXml(root);this.delegate = parent;}

?

4.1profile屬性的使用

這個(gè)特性可以同時(shí)在配置文件中部署兩套配置來適用于生產(chǎn)環(huán)境和開發(fā)環(huán)境,這樣可以方便的進(jìn)行切換開發(fā)、部署環(huán)境,最常用的是更換不同的數(shù)據(jù)庫。

4.2解析并注冊(cè)BeanDefinitions

處理了profile后就可以進(jìn)行XML的讀取了,跟蹤代碼進(jìn)入parseBeanDefinitions(root, this.delegate)

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {// 對(duì)beans的處理if (delegate.isDefaultNamespace(root)) {NodeList nl = root.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if (node instanceof Element) {Element ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {// 對(duì)bean的處理parseDefaultElement(ele, delegate);}else {// 對(duì)bean的處理delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);}}

?

上面的代碼看起來邏輯還是挺清晰的,因?yàn)樵?span lang="en-us">spring的xml配置里面有兩大類bean申明,一個(gè)是默認(rèn)的,一個(gè)是自定義的,兩種方式的讀取及解析差別還是非常大的,如果采用Spring默認(rèn)的配置,spring當(dāng)然知道該怎么做,但是如果是自定義的,那么久需要用戶實(shí)現(xiàn)一些接口及配置了。

對(duì)于標(biāo)簽解析,請(qǐng)看我下一篇文章。

轉(zhuǎn)載于:https://www.cnblogs.com/wcj-java/p/9218239.html

總結(jié)

以上是生活随笔為你收集整理的Spring IOC BeanDefinition解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。