目标
通过在spring的xml配置文件中增加如下配置
<test:amimal id="tomcat" type="cat" name="tom" age="15"/>
然后再java代码中可通过如下代码获取一个叫汤姆猫的动物
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/application.xml");
Animal animal = (Animal)ctx.getBean("tomcat");
System.out.println(animal.getName());
}
实现
1 编写xsd文件
<test:amimal id="tomcat" type="cat" name="tom" age="15"/>
xml中可以配置哪些属性以及属性是数字还是字符串呢,那就需要一个animal.xsd对xml文件做约束,如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
xmlns="http://pigcoffe.com/schema/animal"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://pigcoffe.com/schema/animal"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:element name="animal">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="age" type="xsd:int" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
2 编写和xml对应的JavaBean
package com.pigcoffe;
public class Animal {
private String id;
private String name;
private String type;
private Integer age;
//省略setter geter方法
}
3. 那xml如何解析呢?新建BeanDefinitionParser
package com.pigcoffe;
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 AnimalBeanDefinitionParser extends
AbstractSingleBeanDefinitionParser {
protected Class getBeanClass(Element element) {
return Animal.class;
}
protected void doParse(Element element, BeanDefinitionBuilder bean) {
String name = element.getAttribute("name");
String type = element.getAttribute("type");
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(type)) {
bean.addPropertyValue("type", type);
}
if (StringUtils.hasText(age)) {
bean.addPropertyValue("age", Integer.valueOf(age));
}
}
}
4. 指定animal标签用哪个解析器解析,AnimalNamespaceHandler
package com.pigcoffe;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class AnimalNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("animal", new AnimalBeanDefinitionParser());
}
}
5.配置spring.handlers和spring.schemas告诉spring使用哪个nameSpaceHandler和xsd文件的本地路径
spring.handlers:
http\://pigcoffe.com/schema/animal=com.pigcoffe.AnimalNamespaceHandler
spring.schemas:
http\://pigcoffe.com/schema/animal.xsd=META-INF/animal.xsd
另外还要再spring的application.xml中引入animal.xml 或者是直接写在主配置文件中。
到此运行测试用例,已经可以控制台打印出tom了。
总结
项目结构图:
spring-schema.png
spring自定义标签步总结:
- 分析归纳出自定义标签有哪些需要配置的属性
- 编写xsd文件约束标签
- 根据属性编写对应的javaBean对象
- 编写BeanDefinationParser解析标签和NameSpaceHandler指定标签使用哪个解析器
- 编写spring.handlers和spring.schemas