欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學(xué)堂解析Spring中自定義Schema如何解析生效詳解

2018-07-09 13:21:33 1228瀏覽

隨著SpringBoot的日漸流行,應(yīng)用里的大部分配置都被隱藏了起來,Spring2.5在2.0的基于Schema的Bean配置的基礎(chǔ)之上,再增加了擴(kuò)展XML配置的機(jī)制。通過該機(jī)制,我們可以編寫自己的Schema,并根據(jù)自定義的Schema用自定的標(biāo)簽配置Bean,下面這篇文章主要介紹了關(guān)于Java培訓(xùn)中Spring自定義Schema如何解析生效的詳細(xì)介紹。



但有些時候,由于配置的內(nèi)容在SpringBoot這種零配置中并不能很好的實(shí)現(xiàn),就需要我們?nèi)允褂肵ML的配置形式,然后再ImportSource進(jìn)來?;蛘咭恍╉?xiàng)目受環(huán)境等影響,未使用Boot進(jìn)行開發(fā),此時也需要對配置有一定的了解。

那這次讓我們往回看一些,看看在XML配置中,一些自定義的Schema內(nèi)容,是如何融合到Spring中進(jìn)行配置的。例如:

Springdataes
dubbo

還有許多這樣的例子,我們不再一一羅列。但通過上述兩個圖,我們發(fā)現(xiàn)一個共同的特點(diǎn):

都是通過schemaLocation將對應(yīng)的schema引入

在對應(yīng)的beans元素中增加更具體的自定義配置

這個也是發(fā)生在解析自定義配置文件過程中,有一個resolve的過程,此時會將當(dāng)前classLoader對應(yīng)的所有包含spring.handlers文件加載過來。

我們再來看這個解析類,內(nèi)容如下:

  publicclassElasticsearchNamespaceHandlerextendsNamespaceHandlerSupport{
  publicElasticsearchNamespaceHandler(){
  }
  publicvoidinit(){
  RepositoryConfigurationExtensionextension=newElasticsearchRepositoryConfigExtension();
  RepositoryBeanDefinitionParserparser=newRepositoryBeanDefinitionParser(extension);
  this.registerBeanDefinitionParser("repositories",parser);
  this.registerBeanDefinitionParser("node-client",newNodeClientBeanDefinitionParser());
  this.registerBeanDefinitionParser("transport-client",newTransportClientBeanDefinitionParser());
  }
  }

首先是繼承自NamesapceHandlerSupport

然后在重寫的init方法中注冊了一系列的parser,每個parser對應(yīng)一個字符串,就是我們在xml配置文件是使用的自定義內(nèi)容,比如上面的es的配置

<elasticsearch:transport-clientid="client"
cluster-nodes="192.168.73.186:9300"cluster

這里的配置最終就會通過TransportClientBeanDefinitionParser來進(jìn)行解析

而上面提到的各個parser,在init方法中,保存在了一個Map中

privatefinalMap<String,BeanDefinitionParser>parsers=newHashMap();

所謂注冊parser,就是在向這個parsers的map進(jìn)行put操作。

那回過頭來,在Spring中,最核心的內(nèi)容是什么呢?是Bean。而實(shí)際上我們配置到XML里的這些內(nèi)容,最終也會生在一個對應(yīng)的Bean,所有的配置,只是為了生成Bean,這些自定義的配置,都稱之為BeanDefinition。

所以,Spring在解析配置文件是,會有如下的判斷,是否是defaultNamespace,不是的話就走customElementParse

  protectedvoidparseBeanDefinitions(Elementroot,BeanDefinitionParserDelegatedelegate){
  if(delegate.isDefaultNamespace(root)){
  NodeListnl=root.getChildNodes();
  for(inti=0;i<nl.getLength();++i){
  Nodenode=nl.item(i);
  if(nodeinstanceofElement){
  Elementele=(Element)node;
  if(delegate.isDefaultNamespace(ele)){
  this.parseDefaultElement(ele,delegate);
  }else{
  delegate.parseCustomElement(ele);
  }
  }
  }
  }else{
  delegate.parseCustomElement(root);
  }
  }

而是不是defaultNameSpace的判斷更直接:namespace的uri有沒有內(nèi)容,或者是不是spring的beans的聲明

publicbooleanisDefaultNamespace(StringnamespaceUri){
return!StringUtils.hasLength(namespaceUri)||"http://m.dionly.net.cn/schema/beans".equals(namespaceUri);
}

所以請求都走到了parseCustomElement里,這里開始進(jìn)行配置的解析,parse的時候,通過uriResolver查到對應(yīng)的Handler

  publicBeanDefinitionparseCustomElement(Elementele,BeanDefinitioncontainingBd){
  StringnamespaceUri=this.getNamespaceURI(ele);
  NamespaceHandlerhandler=this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
  if(handler==null){
  this.error("UnabletolocateSpringNamespaceHandlerforXMLschemanamespace["+namespaceUri+"]",ele);
  returnnull;
  }else{
  returnhandler.parse(ele,newParserContext(this.readerContext,this,containingBd));
  }
  }

那此時返回的僅僅是spring.handlers里配置的Handler,而每個Handler又注冊了不少的parse,還得需要一個獲取parser的過程

  publicBeanDefinitionparse(Elementelement,ParserContextparserContext){
  returnthis.findParserForElement(element,parserContext).parse(element,parserContext);
  }
  privateBeanDefinitionParserfindParserForElement(Elementelement,ParserContextparserContext){
  StringlocalName=parserContext.getDelegate().getLocalName(element);
  BeanDefinitionParserparser=(BeanDefinitionParser)this.parsers.get(localName);
  if(parser==null){
  parserContext.getReaderContext().fatal("CannotlocateBeanDefinitionParserforelement["+localName+"]",element);
  }
  returnparser;
  }

這個獲取的過程,就是通過傳入的string,在我們開始聲明的Map里get對應(yīng)的parser,再使用它進(jìn)行配置的解析啦。

有了parser,后面就是生成BeanDefinition的過程。

我們看,這些parser,都是繼承自AbstraceBeanDefinitionParser,或者實(shí)現(xiàn)了BeanDefinitionParser的接口,統(tǒng)一解析的入口處,是接口的parse方法。

  publicclassTransportClientBeanDefinitionParserextendsAbstractBeanDefinitionParser{
  publicTransportClientBeanDefinitionParser(){
  }
  protectedAbstractBeanDefinitionparseInternal(Elementelement,ParserContextparserContext){
  BeanDefinitionBuilderbuilder=BeanDefinitionBuilder.rootBeanDefinition(TransportClientFactoryBean.class);
  this.setConfigurations(element,builder);
  returnthis.getSourcedBeanDefinition(builder,element,parserContext);
  }
  }

在重寫的parseInternal方法中,返回解析配置后對應(yīng)的BeanDefinition。這里也是各個框架自由抽象的地方。比如有些框架是簡單直接一個類,而有些在此處會應(yīng)用一些類似策略、裝飾器等設(shè)計(jì)模式,提供更多的靈活性。

具體獲取到BeanDefinition之后,放到整個Context中如何生成SpringBean的內(nèi)容,以后我們再做分析。

以上就是關(guān)于扣丁學(xué)堂Java開發(fā)Spring自定義Schema如何解析生效的詳細(xì)介紹,希望對大家學(xué)習(xí)有所幫助,想要了解更多內(nèi)容的小伙伴可以登錄扣丁學(xué)堂官網(wǎng)咨詢??鄱W(xué)堂不僅有專業(yè)的老師和與時俱進(jìn)的課程體系,還有大量的Java視頻教程供學(xué)員觀看學(xué)習(xí),想要快速學(xué)習(xí)Java開發(fā)技術(shù)的小伙伴快快行動吧??鄱W(xué)堂H5技術(shù)交流群:559883758。

扣丁學(xué)堂微信公眾號



【關(guān)注微信公眾號獲取更多學(xué)習(xí)資料】



查看更多關(guān)于“Java開發(fā)資訊的相關(guān)文章>>

標(biāo)簽: Java培訓(xùn) Java開發(fā)程序員 Java視頻教程 Spring視頻教程

熱門專區(qū)

暫無熱門資訊

課程推薦

微信
微博
15311698296

全國免費(fèi)咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號中關(guān)村智誠科創(chuàng)大廈4層
京ICP備2021002079號-2   Copyright ? 2017 - 2022
返回頂部 返回頂部