文章目录
前言
使用过spring+dubbo的朋友可能会有问,dubbo的xml标签(如:<dubbo:reference interface="cn.e3mall.content.service.ContentService" id="contentService" />
)是怎么被spring解析并生成bean对象的?
想要了解dubbo和spring的融合,首先需要知道如何在spring中自定义xml标签。
一、总体步骤
- 设计javabean
- 编写XSD(XML Schema Definition)文件 ,定义XML语法规范,校验XML
- 编写NamespaceHandler和BeanDefinitionParser完成解析工作
- 编写spring.handler和spring.schemas串联所有部件
- 在spring配置文件中编写自定义xml标签
- 加载自定义xml标签的bean
二、具体案例
1.设计javabean
javabean代码如下(示例):
public class Person {
private String name;
private int age;
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.编写XSD(XML Schema Definition)约束文件
<xs:schema>
元素中targetNamespace
属性值和xmlns
属性值是一样的
targetNamespace
表示被此 schema 定义的元素所在的命名空间,xmlns表示默认的命名空间
代码如下(示例):
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.wgc.com/schema/wgc"
xmlns="http://www.wgc.com/schema/wgc"
elementFormDefault="qualified">
<xs:element name="person" type="personType"/>
<xs:complexType name="personType">
<xs:attribute name="id" type="xs:string" />
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="age" >
<!--限定属性值在0~120之间-->
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:minInclusive value="0"/>
<xs:maxInclusive value="120"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>
3、bean定义解析器:BeanDefinitionParser
自定义的BeanDefinitionParser需要实现BeanDefinitionParser
接口的parse()方法,而我们继承的spring提供的抽象类AbstractSingleBeanDefinitionParser
已经实现了BeanDefinitionParser
接口
public class WgcBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) {
return Person.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String name = element.getAttribute("name");
int age = Integer.valueOf(element.getAttribute("age"));
builder.addPropertyValue("name", name);
builder.addPropertyValue("age", age);
}
}
4、编写NamespaceHandler
我们自定义的类继承了spring提供的抽象类NamespaceHandlerSupport
registerBeanDefinitionParser()
方法的参数"person"
表示元素名称,也就是在xsd文件中定义的元素<xs:element name="person" type="personType"/>
的name属性值
public class WgcNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("person", new WgcBeanDefinitionParser());
}
}
5、 编写spring.handlers文件
1)此文件放在classpath下的META-INF文件夹下,内容以key=value的形式存放,意思是key代表的命名空间的元素使用value这个handler处理
2)key的值和xsd文件中targetNamespace
的值相同,否则报错
3)value的值是我们自定义的NamespaceHandler
的全限定性类名
http\://www.wgc.com/schema/wgc=com.wgc.custom.xml.schema.WgcNamespaceHandler
6、编写spring.schemas
1)此文件存放在classpath下的META-INF文件夹下,内容为key=value的形式
2)key值一般写为:xsd文件targetNamespace的值+xsd文件名称;如果不遵守此规则,那么应该让key的值和spring配置文件中xsi:schemaLocation
中的value值相同,否则报错
3)value的值就是xsd文件的路径
http\://www.wgc.com/schema/wgc/wgc.xsd=META-INF/wgc.xsd
7、在spring配置文件中编写自定义的xml标签
1)xmlns:wgc="http://www.wgc.com/schema/wgc"
表示下面前缀使用 wgc:
的元素和数据类型来自命名空间"http://www.wgc.com/schema/wgc"
,这个命名空间就是我们在XSD文件中定义的targetNamespace
的值
2)xsi:schemaLocation
的内容是成对存放的,例如:"http://www.wgc.com/schema/wgc"
表示需要使用的命名空间 ,它的值和xmlns:wgc
的值相同,"http://www.wgc.com/schema/wgc/wgc.xsd"
表示命名空间使用的 xsd 的位置,这个地址和我们在spring.schemas
文件中定义的一样
<?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:wgc="http://www.wgc.com/schema/wgc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.wgc.com/schema/wgc http://www.wgc.com/schema/wgc/wgc.xsd">
<wgc:person id="person1" name="wgc" age="25" />
</beans>
8、编写启动类加载bean
public class CustomMainClass {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
Person person = (Person)ac.getBean("person1");
System.err.println(person.toString());
}
}
输出结果:
Person{name='wgc', age=25}
总结
今天只是写了如何在spring中自定义xml标签并使用,并未讲解其原理过程,等以后在进行分析。