Spring的自定義擴(kuò)展標(biāo)簽NamespaceHandler解析
自定義擴(kuò)展標(biāo)簽NamespaceHandler
在很多情況下,我們需要為系統(tǒng)提供可配置化支持,簡(jiǎn)單的做法可以直接基于Spring的標(biāo)準(zhǔn)Bean來(lái)配置,但配置較為復(fù)雜或者需要更多豐富控制的時(shí)候,會(huì)顯得非常笨拙。一般的做法會(huì)用原生態(tài)的方式去解析定義好的xml文件,然后轉(zhuǎn)化為配置對(duì)象,這種方式當(dāng)然可以解決所有問(wèn)題,但實(shí)現(xiàn)起來(lái)比較繁瑣,特別是是在配置非常復(fù)雜的時(shí)候,解析工作是一個(gè)不得不考慮的負(fù)擔(dān)。Spring提供了可擴(kuò)展Schema的支持,這是一個(gè)不錯(cuò)的折中方案,完成一個(gè)自定義
配置一般需要以下步驟:
[1] 設(shè)計(jì)配置屬性和JavaBean
[2] 編寫(xiě)XSD文件
[3] 編寫(xiě)NamespaceHandler和BeanDefinitionParser完成解析工作
[4] 編寫(xiě)spring.handlers和spring.schemas串聯(lián)起所有部件
[5] 在Bean文件中應(yīng)用 下面結(jié)合一個(gè)小例子來(lái)實(shí)戰(zhàn)以上過(guò)程
1)設(shè)計(jì)配置屬性和JavaBean
首先當(dāng)然得設(shè)計(jì)好配置項(xiàng),并通過(guò)JavaBean來(lái)建模,本例中需要配置People實(shí)體,配置屬性name和age(id是默認(rèn)需要的)
public class People { private String id; private String name; private Integer age; }
2)編寫(xiě)XSD文件
為上一步設(shè)計(jì)好的配置項(xiàng)編寫(xiě)XSD文件,XSD是schema的定義文件,配置的輸入和解析輸出都是以XSD為契約,本例中XSD如下:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://blog.csdn.net/cutesource/schema/people" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://blog.csdn.net/cutesource/schema/people" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans" /> <xsd:element name="people"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="age" type="xsd:int" /> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
關(guān)于xsd:schema的各個(gè)屬性具體含義就不作過(guò)多解釋,可以參見(jiàn)//www.w3school.com.cn/schema/schema_schema.asp
<xsd:element name=“people”>對(duì)應(yīng)著配置項(xiàng)節(jié)點(diǎn)的名稱,因此在應(yīng)用中會(huì)用people作為節(jié)點(diǎn)名來(lái)引用這個(gè)配置
<xsd:attribute name=“name” type=“xsd:string” />和<xsd:attribute name=“age” type=“xsd:int” />對(duì)應(yīng)著配置項(xiàng)people的兩個(gè)屬性名,因此在應(yīng)用中可以配置name和age兩個(gè)屬性,分別是string和int類型
完成后需把xsd存放在classpath下,一般都放在META-INF目錄下(本例就放在這個(gè)目錄下)
3)編寫(xiě)NamespaceHandler和BeanDefinitionParser完成解析工作
下面需要完成解析工作,會(huì)用到NamespaceHandler和BeanDefinitionParser這兩個(gè)概念。具體說(shuō)來(lái) NamespaceHandler會(huì)根據(jù)schema和節(jié)點(diǎn)名找到某個(gè)BeanDefinitionParser,然后由 BeanDefinitionParser完成具體的解析工作。因此需要分別完成NamespaceHandler和 BeanDefinitionParser的實(shí)現(xiàn)類,Spring提供了默認(rèn)實(shí)現(xiàn)類NamespaceHandlerSupport和 AbstractSingleBeanDefinitionParser,簡(jiǎn)單的方式就是去繼承這兩個(gè)類。本例就是采取這種方式:
import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class MyNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("people", new PeopleBeanDefinitionParser()); } }
其中registerBeanDefinitionParser(“people”, new PeopleBeanDefinitionParser());就是用來(lái)把節(jié)點(diǎn)名和解析類聯(lián)系起來(lái),在配置中引用people配置項(xiàng)時(shí),就會(huì)用 PeopleBeanDefinitionParser來(lái)解析配置。PeopleBeanDefinitionParser就是本例中的解析類:
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; public class PeopleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return People.class; } protected void doParse(Element element, BeanDefinitionBuilder bean) { String name = element.getAttribute("name"); String age = element.getAttribute("age"); String id = element.getAttribute("id"); if (StringUtils.hasText(id)) { bean.addPropertyValue("id", id); } if (StringUtils.hasText(name)) { bean.addPropertyValue("name", name); } if (StringUtils.hasText(age)) { bean.addPropertyValue("age", Integer.valueOf(age)); } } }
其中element.getAttribute就是用配置中取得屬性值,bean.addPropertyValue就是把屬性值放到bean中。
4)編寫(xiě)spring.handlers和spring.schemas串聯(lián)起所有部件
上面幾個(gè)步驟走下來(lái)會(huì)發(fā)現(xiàn)開(kāi)發(fā)好的handler與xsd還沒(méi)法讓?xiě)?yīng)用感知到,就這樣放上去是沒(méi)法把前面做的工作納入體系中的,spring提供了 spring.handlers和spring.schemas這兩個(gè)配置文件來(lái)完成這項(xiàng)工作,這兩個(gè)文件需要我們自己編寫(xiě)并放入META-INF文件夾 中,這兩個(gè)文件的地址必須是META-INF/spring.handlers和META-INF/spring.schemas,spring會(huì)默認(rèn)去 載入它們,本例中spring.handlers如下所示:
//blog.csdn.net/cutesource/schema/people=study.schemaExt.MyNamespaceHandler 以上表示當(dāng)使用到名為"//blog.csdn.net/cutesource/schema/people"的schema引用時(shí),會(huì)通過(guò)study.schemaExt.MyNamespaceHandler來(lái)完成解析
spring.schemas如下所示:
//blog.csdn.net/cutesource/schema/people.xsd=META-INF/people.xsd 以上就是載入xsd文件
5)在Bean文件中應(yīng)用
到此為止一個(gè)簡(jiǎn)單的自定義配置以完成,可以在具體應(yīng)用中使用了。使用方法很簡(jiǎn)單,和配置一個(gè)普通的spring bean類似,只不過(guò)需要基于我們自定義schema,本例中引用方式如下所示:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cutesource="http://blog.csdn.net/cutesource/schema/people" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://blog.csdn.net/cutesource/schema/people http://blog.csdn.net/cutesource/schema/people.xsd"> <cutesource:people id="test" name="test" age="1"/> </beans>
其中xmlns:cutesource=“//blog.csdn.net/cutesource/schema/people” 是用來(lái)指定自定義schema,xsi:schemaLocation用來(lái)指定xsd文件。<cutesource:people id=“cutesource” name=“zhijun.yuanzj” age=“27”/>是一個(gè)具體的自定義配置使用實(shí)例。
最后就可以在具體程序中使用基本的bean載入方式來(lái)載入我們的自定義配置對(duì)象了,如:
ApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml"); People p = (People)ctx.getBean("cutesource"); System.out.println(p.getId()); System.out.println(p.getName()); System.out.println(p.getAge());
會(huì)輸出:
test test 1
到此這篇關(guān)于Spring的自定義擴(kuò)展標(biāo)簽NamespaceHandler解析的文章就介紹到這了,更多相關(guān)自定義擴(kuò)展標(biāo)簽NamespaceHandler內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用正則表達(dá)式檢索、替換String中特定字符和正則表達(dá)式的一切
這篇文章主要給大家介紹了關(guān)于Java使用正則表達(dá)式檢索、替換String中特定字符和正則表達(dá)式的一切,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09Spring?AOP實(shí)現(xiàn)聲明式事務(wù)機(jī)制源碼解析
這篇文章主要為大家介紹了Spring?AOP實(shí)現(xiàn)聲明式事務(wù)機(jī)制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Spring Cloud之注冊(cè)中心Nacos的使用詳解
本文介紹SpringCloud Alibaba中的Nacos組件,對(duì)比了Nacos與Eureka的區(qū)別,展示了如何在項(xiàng)目中引入SpringCloud Alibaba和Nacos,并配置負(fù)載均衡,通過(guò)實(shí)際操作,驗(yàn)證了服務(wù)注冊(cè)和負(fù)載均衡的功能,感興趣的朋友一起看看吧2025-03-03Springboot實(shí)現(xiàn)定時(shí)任務(wù)的4種方式舉例詳解
在我們開(kāi)發(fā)項(xiàng)目過(guò)程中經(jīng)常需要定時(shí)任務(wù)來(lái)幫助我們來(lái)做一些內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于Springboot實(shí)現(xiàn)定時(shí)任務(wù)的4種方式,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01