隨筆-295  評(píng)論-26  文章-1  trackbacks-0
          2007-07-18 Spring的事務(wù)通知???

          Spring2.0 可擴(kuò)展XML配置初探

          關(guān)鍵字: Spring ? ????

          Spring 2.0版本支持?jǐn)U展XML配置,著實(shí)興奮了一下,在我看來,Spring作為目前最流行的框架,不能擴(kuò)展用戶自定義的配置,實(shí)在是Spring的一個(gè)很不爽的地方,<bean />的方式用起來比較通用,起碼到目前為止符合大部分人的使用習(xí)慣,并且能完成Spring所有的配置操作,但是對(duì)于第三方的提供商或則會(huì)經(jīng)常擴(kuò)展Spring功能的開發(fā)者來說,使用<bean />這樣的配置方式或許不是他們最想要的,他們需要使組件的配置更加直觀、易閱讀、易擴(kuò)展……試想使用下面的配置方式

          代碼
          1. <mytag:datasource?id= "datasource" ? ??
          2. ???????databaseType= "oracle" ? ??
          3. ???????ip= "192.168.1.110" ? ??
          4. ???????port= "1521" ? ??
          5. ???????databaseName= "myDB" ??
          6. ???????userName= "admin" ??
          7. ???????password= "password" ??
          8. ???????/> ??
          9. ??
          10. <mytag:ehCache?id= "ehcache" ? ??
          11. ???????cache= "true" ? ??
          12. ???????maxElements= "100000" ? ??
          13. ???????timeToIdleSeconds= "120" ? ??
          14. ???????timeToLiveSeconds= "120" ??
          15. ???????overflowToDisk= "true" ??
          16. ???????/> ??

          上面的代碼中配置了兩個(gè)組件,datasource和cache組件,相比普通的bean&propertiy方式,很顯然,這種配置方式更直觀,更易讀,更重要的是,如果作為組件發(fā)布,使用者也可以很方便快捷的開始使用,而不需要關(guān)心組件的任何實(shí)現(xiàn)細(xì)節(jié)。

          擴(kuò)展XML配置大致需要一下幾個(gè)步驟
          1、創(chuàng)建一個(gè)需要擴(kuò)展的組件
          2、定義一個(gè)xsd文件描述組件內(nèi)容
          3、創(chuàng)建一個(gè)文件,實(shí)現(xiàn)BeanDefinitionParser接口,用來解析xsd文件中的定義和組件定義
          4、創(chuàng)建一個(gè)Handler文件,擴(kuò)展自NamespaceHandlerSupport,目的是將組件注冊(cè)到Spring容器
          5、編寫spring.handlers和spring.schemas文件

          提供一個(gè)簡(jiǎn)單的例子,來說明如何去擴(kuò)展一個(gè)Spring配置,需求如下:使用自定義標(biāo)簽定義一個(gè)簡(jiǎn)單的bean,這個(gè)bean有一個(gè)或多個(gè)屬性,標(biāo)簽定義完成后,可以在其他項(xiàng)目中用自定義標(biāo)簽來定義該bean。

          首先,創(chuàng)建一個(gè)需要擴(kuò)展的組件,在這里只是一個(gè)簡(jiǎn)單的bean,而且這個(gè)bean只有一個(gè)屬性age.
          One.java

          代碼
          1. package?com.mysite.tag; ??
          2. ??
          3. public?class?One?{ ??
          4. ????private?String?age; ??
          5. ???? ??
          6. ????public?One(){ ??
          7. ???????? ??
          8. ????} ??
          9. ??
          10. ????public?String?getAge()?{ ??
          11. ????????return?age; ??
          12. ????} ??
          13. ??
          14. ????public?void?setAge(String?age)?{ ??
          15. ????????this.age?=?age; ??
          16. ????} ??
          17. } ??

          然后,建立一個(gè)xsd文件,來描述這個(gè)bean
          mytag.xsd

          代碼
          1. <?xml?version="1.0"?encoding="UTF-8"?>??
          2. <xsd:schema?xmlns="http://www.mysite.org/schema/mytag"??
          3. ????????xmlns:xsd="http://www.w3.org/2001/XMLSchema"??
          4. ????????xmlns:beans="http://www.springframework.org/schema/beans"??
          5. ????????targetNamespace="http://www.mysite.org/schema/mytag"??
          6. ????????elementFormDefault="qualified"??
          7. ????????attributeFormDefault="unqualified">??
          8. ???? ??
          9. ????<xsd:import?namespace="http://www.springframework.org/schema/beans"/>??
          10. ???? ??
          11. ????<xsd:element?name="one">??
          12. ????????<xsd:complexType>??
          13. ????????????<xsd:complexContent>??
          14. ????????????????<xsd:extension?base="beans:identifiedType">??
          15. ????????????????????<xsd:attribute?name="age"?type="xsd:string"?default="99999"/>??
          16. ????????????????</xsd:extension>??
          17. ????????????</xsd:complexContent>??
          18. ????????</xsd:complexType>??
          19. ????</xsd:element>??
          20. </xsd:schema>??

          在上面的xsd文件描述了一個(gè)新的targetNamespace,并在這個(gè)空間中定義了一個(gè)name為one的element,one有一個(gè)age屬性,類型為string,默認(rèn)值為99999.xsd文件是xml DTD的替代者,使用XML Schema語言進(jìn)行編寫,這里對(duì)xsd schema不做太多解釋,有興趣可以參考相關(guān)的資料。

          創(chuàng)建一個(gè)Java文件,該文件實(shí)現(xiàn)了BeanDefinitionParser接口,用來解析xsd文件中的定義并注冊(cè)到組件中。
          MyBeanDefinitionParser.java

          代碼
          1. package?com.mysite.tag; ??
          2. ??
          3. import?org.springframework.beans.factory.config.BeanDefinition; ??
          4. import?org.springframework.beans.factory.config.BeanDefinitionHolder; ??
          5. import?org.springframework.beans.factory.support.BeanDefinitionReaderUtils; ??
          6. import?org.springframework.beans.factory.support.RootBeanDefinition; ??
          7. import?org.springframework.beans.factory.xml.BeanDefinitionParser; ??
          8. import?org.springframework.beans.factory.xml.ParserContext; ??
          9. import?org.w3c.dom.Element; ??
          10. ??
          11. public?class?MyBeanDefinitionParser?implements?BeanDefinitionParser{ ??
          12. ????public?BeanDefinition?parse(Element?arg0,?ParserContext?arg1)?{ ??
          13. ????????RootBeanDefinition?def?=?new?RootBeanDefinition(); ??
          14. ????????????????//設(shè)置Bean?Class ??
          15. ????????def.setBeanClass(One.class); ??
          16. ???????? ??
          17. ????????????????//注冊(cè)ID屬性 ??
          18. ????????String?id?=?arg0.getAttribute("id"); ??
          19. ????????BeanDefinitionHolder?idHolder=?new?BeanDefinitionHolder(def,id); ??
          20. ????????BeanDefinitionReaderUtils.registerBeanDefinition(idHolder,?arg1.getRegistry()); ??
          21. ???????? ??
          22. ????????????????//注冊(cè)age屬性 ??
          23. ????????String?age?=?arg0.getAttribute("age"); ??
          24. ????????BeanDefinitionHolder?ageHolder=?new?BeanDefinitionHolder(def,age); ??
          25. ????????BeanDefinitionReaderUtils.registerBeanDefinition(ageHolder,?arg1.getRegistry()); ??
          26. ????????def.getPropertyValues().addPropertyValue("age",?age); ??
          27. ???????? ??
          28. ????????return?def; ??
          29. ????} ??
          30. } ??
          31. ??

          上面的代碼僅僅實(shí)現(xiàn)了一個(gè)方法public BeanDefinition parse(Element arg0, ParserContext arg1),設(shè)置相關(guān)的Bean Class,解析了對(duì)應(yīng)的xsd文件,并將解析的內(nèi)容注冊(cè)到上下文中,同時(shí)返回一個(gè)BeanDefinition對(duì)象(BeanDefinition是Spring的bean定義,提供了bean部分的操作方法,如isSingleton()、isLazyInit()等)。

          注意,id屬性是一個(gè)默認(rèn)的屬性,可以不在xsd文件中描述,但是需要注冊(cè)它,否則將無法通過getBean方法獲取標(biāo)簽定義的bean,也無法被其他bean引用。
          另外,下面代碼是給bean的屬性賦值,這個(gè)是不可缺少的,否則在使用標(biāo)簽定義時(shí)將無法獲取bean屬性的值。

          代碼
          1. def.getPropertyValues().addPropertyValue("age",?age); ??

          然后為組件編寫一個(gè)Handler文件,擴(kuò)展自NamespaceHandlerSupport,它的作用是將組件注冊(cè)到Spring容器
          MyNameSpaceHandler.java

          代碼
          1. package?com.mysite.tag; ??
          2. ??
          3. import?org.springframework.beans.factory.xml.NamespaceHandlerSupport; ??
          4. ??
          5. public?class?MyNameSpaceHandler?extends?NamespaceHandlerSupport?{ ??
          6. ??
          7. ????public?void?init()?{ ??
          8. ?????????registerBeanDefinitionParser("one",new?MyBeanDefinitionParser()); ??
          9. ????} ??
          10. } ??

          實(shí)際執(zhí)行的過程只有一句代碼,注冊(cè)了一個(gè)名字為one的擴(kuò)展配置,包含了MyBeanDefinitionParser所parser相關(guān)xsd的內(nèi)容。

          到了這里,一個(gè)Spring擴(kuò)展標(biāo)簽已經(jīng)完成,但是我們目前還沒辦法使用它,Spring沒那么聰明,它無法知道我們?cè)谑裁吹胤蕉x了哪些擴(kuò)展標(biāo)簽,這些標(biāo)簽將被誰解析,這個(gè)過程要我們通過一些文件來告知Spring知道,它們就是spring.handlers和spring.schemas,它們放在META-INF目錄中,Spring.jar的META-INF目錄中也有同名的文件,它們的文件內(nèi)容基本上是相似的,而Spring在執(zhí)行過程中,如果發(fā)現(xiàn)其他jar文件的META-INF文件夾中包含有這兩個(gè)文件,Spring將會(huì)合并它們。
          spring.schemas

          代碼
          1. http\://www.mysite.org/schema/mytag.xsd=com/mysite/tag/mytag.xsd ??

          spring.handlers

          代碼
          1. http\://www.mysite.org/schema/mytag=com.mysite.tag.MyNameSpaceHandler ??

          spring.schemas將告訴Spring配置文件知道,如果在配置中引用http://www.mysite.org/schema/mytag.xsd,它應(yīng)該去什么地方找相應(yīng)的xsd文件。
          而spring.handlers文件將告訴Spring,應(yīng)該使用哪個(gè)Handler注冊(cè)擴(kuò)展標(biāo)簽。

          現(xiàn)在為止,一個(gè)完整的xml擴(kuò)展標(biāo)簽全部完成,做一個(gè)小應(yīng)用測(cè)試一下。
          將整個(gè)項(xiàng)目打包成jar文件(別忘記META-INF內(nèi)的兩個(gè)文件),然后新建一個(gè)項(xiàng)目,引用剛才打包的jar文件,并引用Spring相關(guān)文件。
          需要注意,自定義xml擴(kuò)展配置只有xsd方式的引用才可以使用.
          application.xml

          代碼
          1. <?xml?version="1.0"?encoding="UTF-8"?>??
          2. <beans?xmlns="http://www.springframework.org/schema/beans"??
          3. ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
          4. ????xmlns:tag="http://www.mysite.org/schema/mytag"??
          5. ????xsi:schemaLocation="http://www.springframework.org/schema/beans ??
          6. ????http://www.springframework.org/schema/beans/spring-beans-2.0.xsd ??
          7. ????http://www.mysite.org/schema/mytag ??
          8. ????http://www.mysite.org/schema/mytag.xsd">??
          9. ??
          10. ????<tag:one?id="oneBean"?age="99"/>??
          11. </beans>??

          在xml文件引用上可以看到,配置了一個(gè)名字為tag的名稱空間,目標(biāo)為http://www.mysite.org/schema/mytag命名空間,這個(gè)目標(biāo)名稱空間必須是存在于項(xiàng)目的引用中的(mytag.xsd中所定義的).
          代碼
          1. <tag:one?id="oneBean"?age="99"/> ??

          上面定義了一個(gè)id為oneBean的組件,使用了“one”擴(kuò)展標(biāo)簽,也就是我們?cè)趆andler中所注冊(cè)的,組件age屬性的值為99。

          Main.java

          代碼
          1. package?com.test; ??
          2. ??
          3. import?org.springframework.context.ApplicationContext; ??
          4. import?org.springframework.context.support.ClassPathXmlApplicationContext; ??
          5. ??
          6. import?com.mysite.tag.One; ??
          7. ??
          8. public?class?Main?{ ??
          9. ??
          10. ????public?static?void?main(String[]?args)?{ ??
          11. ????????ApplicationContext?ctx?=?new?ClassPathXmlApplicationContext("application.xml"); ??
          12. ????????One?tag?=?(One)?ctx.getBean("oneBean"); ??
          13. ????????System.out.println("oneBean?age?is?"+tag.getAge()); ??
          14. ????} ??
          15. } ??

          運(yùn)行測(cè)試程序,結(jié)果如下
          代碼
          1. oneBean?age?is?99??

          Spring的xml擴(kuò)展是一個(gè)非常有用的特性,在Spring2.0的版本中也提供了一些新的標(biāo)簽使用,如<aop>,<tx>等,但就目前來講受大家關(guān)注程度并不高,我想大部分使用Spring的開發(fā)人員都在使用Spring開發(fā)企業(yè)應(yīng)用,而Spring所提供的<bean />定義的方式對(duì)于開發(fā)人員來說已經(jīng)能夠滿足需要,但是如果看的更遠(yuǎn)一些,在Spring以后的發(fā)展過程中,xml擴(kuò)展應(yīng)該會(huì)成為spring的核心特性之一,或許到時(shí)大家會(huì)習(xí)慣這樣的方式來編寫Spring配置文件吧

          代碼
          1. <XXCompany:XXXModule?id=""> ??
          2. ... ??
          3. ... ??

          最后更新:2007-07-18 16:03
          15:42??|?? 永久鏈接??|?? 瀏覽?(481)??|?? 評(píng)論?(2)??| ?? 收藏??|?? 進(jìn)入論壇??|??
          評(píng)論 ???共 2 條 發(fā)表評(píng)論
          baallee ??? 2007-07-18 15:53

          代碼
          1. <? xml ? version = "1.0" ? encoding = "UTF-8" ?> ? ??
          2. < beans ? xmlns = "http://www.springframework.org/schema/beans" ???? ??
          3. xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" ???? ??
          4. xmlns:p = "http://www.springframework.org/schema/p" ???? ??
          5. xsi:schemaLocation ="http://www.springframework.org/schema/beans???????? ??
          6. http://www.springframework.org/schema/beans/spring-beans.xsd" > ?? ??
          7. < bean ? class = "com.interface21.spring2.ioc.Person" ????? ??
          8. p:name = "Tony" ???? ??
          9. p:age = "53" ????? ??
          10. p:house-ref = "number10" ? /> ??? ??
          11. < bean ? class = "com.interface21.spring2.ioc.House" ????? ??
          12. id = "number10" ???? ??
          13. p:name = "10?Downing?Street" /> ?? ??
          14. </ beans > ??

          對(duì)于簡(jiǎn)單的應(yīng)用可以用p標(biāo)簽就好了。
          自定意擴(kuò)展應(yīng)該用在更多的高級(jí)應(yīng)用上



          大盤預(yù)測(cè) 國(guó)富論
          posted on 2007-08-29 15:08 華夢(mèng)行 閱讀(278) 評(píng)論(0)  編輯  收藏 所屬分類: Spring
          主站蜘蛛池模板: 盐源县| 渭源县| 福海县| 依安县| 积石山| 镇巴县| 板桥市| 长顺县| 黄骅市| 聂荣县| 琼中| 喀喇沁旗| 浦县| 洞口县| 腾冲县| 冕宁县| 白玉县| 金乡县| 营山县| 崇阳县| 永嘉县| 锡林浩特市| 文山县| 临颍县| 浮山县| 巴里| 九龙坡区| 福州市| 威信县| 卓资县| 上蔡县| 威宁| 寿宁县| 鄂州市| 平昌县| 灵寿县| 临江市| 余姚市| 东阿县| 中牟县| 婺源县|