扩展自定义标签步骤(前提要把 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="[email protected]" /> </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, [email protected]
工程目录结构: