盒子
盒子
文章目录
  1. 整体思路
    1. 创建模型类
    2. 创建xsd文件
    3. 编写spring.schemas
    4. 编写BeanDefinition,解析xml
    5. 编写NamespaceHandlerSupport
    6. 编写spring.handlers
    7. 测试:创建spring.xml
    8. 测试代码

spring自定义标签

整体思路

  • 创建一个需要扩展的组件
  • 定义一个XSD文件,描述组件内容
  • 创建一个java类,实现BeanDefinitionParser接口,用来解析XSD文件中的定义和组件定义
  • 创建一个Handler类,扩展子NameSpaceHandlerSupport,目的是将组件注册到容器。
  • 编写(添加)Spring.handlers和Spring.schemas文件。

解析流程:通过Spring.schemas找到对应的XSD文件,校验xml格式;通过Spring.handlers找到对应的NamespaceHandler类作为解析自定义标签的类,通过init方法中的参数BeanDefinition实现类,根据解析的值生成BeanDefinition,

目录结构
xxx


创建模型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Apple {
private String name;
private String appleColor;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAppleColor() {
return appleColor;
}
public void setAppleColor(String appleColor) {
this.appleColor = appleColor;
}
}

创建xsd文件

对于该类标签的定义,spring中有着相应的XSD定义文档
http://www.springframework.org/schema/beans
对于XSD,简单的说是xml的一个标签的定义,在这里就不对XSD过多的解释了,祥见
http://www.w3school.com.cn/schema/schema_example.asp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.zyx.com/schema/apple"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.zyx.com/schema/apple"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd" />
<xsd:element name="apple">
<xsd:complexType>
<xsd:all>
<xsd:element ref="apple-color" minOccurs="1" maxOccurs="1"/>
</xsd:all>
<xsd:attribute name="id" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="apple-color">
<xsd:complexType>
<xsd:attribute name="color" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>

type是用来定义该属性的格式,例如
xsd:string 表示是一个字符串,对格式没什么要求
xsd:id 表示该属性的值是一个id,有格式要求(例如不能以数字开头)。
xsd:IDREF 表示该属性的值与某xsd:id属性的值对应
其他还有很多,例如number,double,datetime等等。


编写spring.schemas

改配置文件主要是用一个url来映射我们第一步配置好的文件,形式如下

1
http\://www.zyx.com/schema/apple.xsd=META-INF/namespace/apple.xsd


编写BeanDefinition,解析xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class AppleBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {

protected Class getBeanClass(Element element) {
return Apple.class;
}

protected void doParse(Element element, BeanDefinitionBuilder bean) {
String name = element.getAttribute("name");
String color = parseAppleColor(element);

if (StringUtils.hasText(name)) {
bean.addPropertyValue("name", name);
}
if (StringUtils.hasText(color)) {
bean.addPropertyValue("appleColor", color);
}
}

private String parseAppleColor(Element element) {
Element colorElement = DomUtils.getChildElementByTagName(element, "apple-color");
return colorElement.getAttribute("color");
}
}

编写NamespaceHandlerSupport

我们配置了com.zyx.demo.springNamespace.AppleNamespaceHandler类作为解析自定义标签的类,所以namespace为apple的标签,都会用这里注册的标签解析器来解析

1
2
3
4
5
public class AppleNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("apple",new AppleBeanDefinitionParser());
}
}


编写spring.handlers

这个配置文件用来配置解析我们apple标签,然后生成一些BeanDefinition进行注册

1
http\://www.zyx.com/schema/apple=com.zyx.demo.springNamespace.AppleNamespaceHandler

到这里就写完了,下面是测试


测试:创建spring.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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:myname="http://www.zyx.com/schema/apple"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.zyx.com/schema/apple http://www.zyx.com/schema/apple.xsd"
default-autowire="byName">

<myname:apple id="xxx" name="hongfushi">
<myname:apple-color color="red"></myname:apple-color>
</myname:apple>

</beans>

测试代码

1
2
3
4
5
6
7
8
9
10
11
12
@Controller
@RequestMapping("/test")
public class TestSpringNamespace {

@ResponseBody
@RequestMapping("spring/namespace")
public String test(){
Apple apple = SpringUtils.getBean(Apple.class);
System.out.println(apple.toString());
return apple.toString();
}
}