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