首先声明

Spring 2.0已经把aop、transaction/tx、jndi和Web MVC等等配置放入单独的namespace中(从spring.jar!/META-INF/spring.handlers中就能找到)。

老式的bean定义虽然可以适合绝大部分的配置工作,但是在一些特殊领域难免显得冗长拖沓,这些领域往往有自己的领域定义,继续沿用老式的bean定义除了会把人搞晕以外倒也没有其他恶行,这种情景之下,使用自己的namespace然后通过自定义的NamespaceHandler去注册bean可以使得编写XML配置的时候更加符合特定领域的语义要求,增强XML文件的可读性。

代码均摘抄自spring-reference.pdf

分为四步:

第一: Authoringan XML schema to describe your custom element(s).

            为你自定义的元素编写一个xml  schema文档

   
   
   
   
  1.  
  2. xml version="1.0" encoding="UTF-8"?> 
  3. <xsd:schemaxmlnsxsd:schemaxmlns="http://www.mycompany.com/schema/myns" 
  4. xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  5. xmlns:beans="http://www.springframework.org/schema/beans" 
  6. targetNamespace="http://www.mycompany.com/schema/myns" 
  7. elementFormDefault="qualified" 
  8. attributeFormDefault="unqualified"> 
  9. <xsd:importnamespacexsd:importnamespace="http://www.springframework.org/schema/beans"/> 
  10. <xsd:element name="dateformat"> 
  11. <xsd:complexType> 
  12. <xsd:complexContent> 
  13. <xsd:extension base="beans:identifiedType"> 
  14. <xsd:attribute name="lenient" type="xsd:boolean"/> 
  15. <xsd:attribute name="pattern" type="xsd:string" use="required"/> 
  16. xsd:extension> 
  17. xsd:complexContent> 
  18. xsd:complexType> 
  19. xsd:element> 
  20. xsd:schema> 

照这种形式使用

   
   
   
   
  1. <myns:dateformatidmyns:dateformatid="dateFormat" 
  2. pattern="yyyy-MM-dd HH:mm" 
  3. lenient="true"/> 

得到的与下述代码一样

   
   
   
   
  1. <bean id="dateFormat" class="java.text.SimpleDateFormat"> 
  2. <constructor-argvalueconstructor-argvalue="yyyy-HH-dd HH:mm"/> 
  3. <property name="lenient" value="true"/> 
  4. bean> 

备注:我schema编写能力不行,得学习

第二步:Coding aNamespaceHandler(实现一个NamespaceHandler)

NamespaceHandler这个接口是很简单的,只有三个方法

   
   
   
   
  1.  init()- allows for initialization of the NamespaceHandlerand will be called by Spring before 
  2. the handler is used 
  3.  
  4. • BeanDefinition parse(Element, ParserContext)-  called when Spring encounters a top-level element (not nested inside a bean definition or a different namespace). This method can 
  5. register bean definitions itself and/or return a bean definition. 
  6.  
  7. • BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)
  8.   called when Spring encounters an attribute or nested element of a different namespace. 

但是spring给我们提供了一个实现了大量公共的逻辑抽象类,我们只需要继承它就行了,不需要重复写很多繁琐的代码,这个类就是NamespaceHandlerSupport

   
   
   
   
  1. package org.springframework.samples.xml; 
  2. import org.springframework.beans.factory.xml.NamespaceHandlerSupport; 
  3. public class MyNamespaceHandler extends NamespaceHandlerSupport { 
  4. public void init() { 
  5. registerBeanDefinitionParser("dateformat"new SimpleDateFormatBeanDefinitionParser()); 

这个类中,你可以注册许多BeanDefinitionParsers,每一个BeanDefinitionParsers用于解析一个自定义element。

第三步:Coding a  BeanDefinitionParser(编写一个  BeanDefinitionParser类)

   
   
   
   
  1. package org.springframework.samples.xml; 
  2. import org.springframework.beans.factory.support.BeanDefinitionBuilder; 
  3. import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; 
  4. import org.springframework.util.StringUtils; 
  5. import org.w3c.dom.Element; 
  6. import java.text.SimpleDateFormat; 
  7. public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {  
  8.  
  9. protected Class getBeanClass(Element element) { 
  10. return SimpleDateFormat.class; # 
  11. }
  12.  
  13. protected void doParse(Element element, BeanDefinitionBuilder bean) { 
  14. // this will never be null since the schema explicitly requires that a value be supplied 
  15. String pattern = element.getAttribute("pattern"); 
  16. bean.addConstructorArg(pattern); 
  17. // this however is an optional property 
  18. String lenient = element.getAttribute("lenient"); 
  19. if (StringUtils.hasText(lenient)) { 
  20. bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); 

同样的,我们也可以继承  AbstractSingleBeanDefinitionParser 这个类   个人觉得,当你只需要注册一个BeanDefinitionParser的时候,你可以继承  AbstractSingleBeanDefinitionParser 这个抽象类,但是如果你的 NamespaceHandler需要多个 BeanDefinitionParser。你就不应该继承这个类。应该继承另外一个抽象类(已验证)

第四步:Registering the handler and the schema(把咱们写的hanlder和schema让spring知道)

编码已经完成了,接下来,我们需要分开将我们自定义的namespaceHandler和schema注册到spring.handlers.properties和spring.schemas.properties文件中,然后将文件放到自己的项目的META-INF文件夹中,注意,名字一定不能改。

 

spring.handlers.properties中配置格式

(注意,properties文件中分号是特殊字符,所以需要转义)

http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler

 

spring.schemas.properties中的配置格式

(此处分号也是需要转义的)

http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd

第五步:现在你就可以使用了

   
   
   
   
  1. xml version="1.0" encoding="UTF-8"?> 
  2. <beansxmlnsbeansxmlns="http://www.springframework.org/schema/beans" 
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  4. xmlns:myns="http://www.mycompany.com/schema/myns" 
  5. xsi:schemaLocation=" 
  6. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
  7. http://www.mycompany.com/schema/myns http://www.mycompany.com/schema/myns/myns.xsd"> 
  8.  
  9. <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/> 
  10.  
  11. <bean id="jobDetailTemplate" abstract="true"> 
  12. <property name="dateFormat"> 
  13.  
  14. <myns:dateformat pattern="HH:mm MM-dd-yyyy"/> 
  15. property> 
  16. bean> 
  17. beans> 

比较简单,算是一个介绍把。感谢