Spring中支持标签级的扩展,例如用到的dubbo和axis2,都可以看到在Spring配置文件中配置各自框架的自定义标签。今天咱们就来尝试自己配置一个自定义标签。
配置自定义标签的过程有以下四个步骤
下面来安装上述步骤来自定义Spring标签。
以下面的日期格式化为例,咱要自顶一个一个日期格式化的标签,并且可以指定日期的格式。
<myns:dateformat id="dateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/>
在com/jialeens/xml目录下创建一个xml文件,命名为myns.xsd。
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.jialeens.com/schema/myns" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://www.mycompany.com/schema/myns" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans"/> <xsd:element name="dateformat"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="lenient" type="xsd:boolean"/> <xsd:attribute name="pattern" type="xsd:string" use="required"/> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>
现在咱们实现一个NamespaceHandler的子类,他的作用是去注册标签和对应的xml解析的类
package com.jialeens.xml; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; public class MyNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("dateformat", new SimpleDateFormatBeanDefinitionParser()); } }
BeanDefinitionParser的作用是去解析Spring中配置的xml配置信息,他负责去解析标签中的属性和配置信息。同时,负责去构建自己要定义的bean。
package com.jialeens.xml; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.util.StringUtils; import org.w3c.dom.Element; import java.text.SimpleDateFormat; public class SimpleDateFormatBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { protected Class getBeanClass(Element element) { return SimpleDateFormat.class; } protected void doParse(Element element, BeanDefinitionBuilder bean) { // this will never be null since the schema explicitly requires that a value be supplied String pattern = element.getAttribute("pattern"); bean.addConstructorArg(pattern); // this however is an optional property String lenient = element.getAttribute("lenient"); if (StringUtils.hasText(lenient)) { bean.addPropertyValue("lenient", Boolean.valueOf(lenient)); } } }
实现了上述的schema和handler与parser,现在需要在Spring中实现注册功能,
在META-INF下面创建两个文件spring.handlers和spring.schemas,内容如下:
spring.handlers:
http/://www.jialeens.com/schema/myns=com.jialeens.xml.MyNamespaceHandler
spring.schemas:
http/://www.jialeens.com/schema/myns.xsd=myns.xsd
上面的作用分别将namespace和handler进行了绑定,同时也将xsd与真正的文件进行了绑定
进行了上述的配置之后,就可以进行测试了
首先创建一个简单的Spring配置文件,myns.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:myns="http://www.mycompany.com/schema/myns" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.jialeens.com/schema/myns http://www.jialeens.com/schema/myns.xsd"> <myns:dateformat id="defaultDateFormat" pattern="yyyy-MM-dd HH:mm" lenient="true"/> <bean id="jobDetailTemplate" abstract="true"> <property name="dateFormat"> <!-- as an inner bean --> <myns:dateformat pattern="HH:mm MM-dd-yyyy"/> </property> </bean> </beans>
然后再写一个测试类
package com.jialeens.xml; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import java.text.SimpleDateFormat; import java.util.Date;</span> <span style="font-family: 'comic sans ms', sans-serif;"> public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("myns.xml"); SimpleDateFormat info = (SimpleDateFormat) context.getBean("dateFormat"); System.out.println(info.format(new Date())); } }
运行后,可以看到控制台输出了当前的时间
XML通常通过DTD、XSD定义,但DTD的表达能力较弱,XSD定义则能力比较强,能够定义类型,出现次数等。自定义标签需要XSD支持,在实现时使用Namespace扩展来支持自定义标签。
从上面的示例可以看到,对于每一个标签,都可以认为他等同于一个bean,例如上面xml中的jobDetailTemplate,只不过使用标签可以使xml中的定义更个性化,同时也更容易辨识出其具体的作用。
相关资料
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xml-custom