扩展自定义标签步骤(前提要把 Spring Core 包加入项目):
- 创建一个需要扩展的组件
- 定义一个 XSD 文件描述组件内容
- 创建一个文件,实现 BeanDefinitionParse 接口,用来解析 XSD 文件中的定义和组件定义
- 创建一个 Handler 文件,扩展自 NamespaceHandlerSupport,目的是将组件注册到 Spring 容器
- 编写 Spring.handlers 和 Spring.schemas 文件
(1) 我们首先创建一个 User 类:只是用来接收配置文件
package main.java.com.wenniuwuren.spring.customize.tag;
/**
* 1. 创建一个需要扩展的组件
* Created by hzzhuyibin on 2016/11/14.
*/
public class User {
private String userName;
private String email;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
(2) 定义一个 XSD 文件描述组件内容:定义了一个新的 targetNamespace,并在这个空间中定义了一个 name 为 user 的 element,user 有 3个属性 id,userName,email。
customizeBeanTest.xml:
targetNamespace 是一个 xml 的 schema 中的概念,表示 user 属于 http://www.wenniuwuren.com/schema/user 这个命名空间。自定义标签命名空间都是自己定义的。在其他 xml 中引入自定义的命名空间,就能使用自定义标签了。
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.wenniuwuren.com/schema/user"
elementFormDefault="qualified">
<element name="user">
<complexType>
<attribute name="id" type="string" />
<attribute name="userName" type="string" />
<attribute name="email" type="string" />
</complexType>
</element>
</schema>
(3) 创建一个文件,实现 BeanDefinitionParse 接口,用来解析 XSD 文件中的定义和组件定义。
UserBeanDefinitionParse
package main.java.com.wenniuwuren.spring.customize.tag;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* 3. 创建一个文件, 实现 AbstractSingleBeanDefinitionParser 接口,用来解析 XSD 文件中的定义和组件定义
* Created by hzzhuyibin on 2016/11/14.
*/
public class UserBeanDefinitionParse extends AbstractSingleBeanDefinitionParser {
// Element 对应的类
protected Class getBeanClass(Element element) {
return User.class;
}
// 从 element 中解析并提取对应的元素
protected void doParse(Element element, BeanDefinitionBuilder bean) {
String userName = element.getAttribute("userName");
String email = element.getAttribute("email");
// 将提取的数据放入到 BeanDefinitionBuilder 中,待到完成所有 bean 的解析后统一注册到 beanFactory 中
if (StringUtils.hasText(userName)) {
bean.addPropertyValue("userName", userName);
}
if (StringUtils.hasText(email))
bean.addPropertyValue("email", email);
}
}
(4) 创建一个 Hanlder 文件,目的是将组件注册到 Spring 容器
遇到自定义标签 <user:aaa 这样类似于 user 开头的元素,就会把这个元素扔给对应的UserBeanDefinitionParse 去接信息
package main.java.com.wenniuwuren.spring.customize.tag;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
* 4. 创建一个 Hanlder 文件,继承自 NamespaceHandlerSupport,目的是将组件注册到 Spring 容器
*
* 遇到自定义标签 <user:aaa 这样类似于 user 开头的元素,就会把这个元素扔给对应的UserBeanDefinitionParse 去接信息
* Created by hzzhuyibin on 2016/11/14.
*/
public class MyNamespaceHandler extends NamespaceHandlerSupport{
@Override
public void init() {
registerBeanDefinitionParser("user", new UserBeanDefinitionParse());
}
}
(5) 编写 Spring.handlers 和 Spring.schemas 文件,默认在工程的 /META-INF/ 文件夹下,当然,也可以通过 Spring 的扩展或者修改源码的方式改变路径
spring.handlers :
http\://www.wenniuwuren.com/schema/user=main.java.com.wenniuwuren.spring.customize.tag.MyNamespaceHandler
spring.schemas:
http\://www.wenniuwuren.com/schema/user.xsd=META-INF/customizeBeanTest.xml
到此,自定义配置就完成了。Spring 加载自定义标签大致流程是遇到自定义标签后,去 spring.handlers 和 spring.schemas 中去找对应的 handler 和 XSD,进而有找到对应的 handler 以及解析元素的 parse。
(6) 创建测试配置文件:在配置文件中引入对应的命名空间以及 XSD 后,就可以直接使用自定义标签了。
引用自定义标签 xsd: xsi:schemaLocation="http://www.wenniuwuren.com/schema/user
http://www.wenniuwuren.com/schema/user.xsd"
定义使用自定义标签的命名空间 "http://www.wenniuwuren.com/schema/user" 和前缀 wenniuwuren : xmlns:wenniuwuren="http://www.wenniuwuren.com/schema/user"
<?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:wenniuwuren="http://www.wenniuwuren.com/schema/user"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.wenniuwuren.com/schema/user http://www.wenniuwuren.com/schema/user.xsd">
<wenniuwuren:user id="testCustomizeBean" userName="aaa" email="bbb@wenniuwuren.com" />
</beans>
(7) 测试
package main.java.com.wenniuwuren.spring.customize.tag;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by hzzhuyibin on 2016/11/14.
*/
public class Test {
public static void main(String[] args) {
ApplicationContext bf = new ClassPathXmlApplicationContext("main/resources/testCustomizeBean.xml");
User user = (User) bf.getBean("testCustomizeBean");
System.out.println(user.getUserName() + ", " + user.getEmail());
}
}
运行结果:
aaa, bbb@wenniuwuren.com
工程目录结构: