- 前言
- 第一部分 核心实现
- 第 1 章 Spring 整体架构和环境搭建
- 第 2 章 容器的基本实现
- 第 3 章 默认标签的解析
- 第 4 章 自定义标签的解析
- 第 5 章 bean 的加载
- 第 6 章 容器的功能扩展
- 第 7 章 AOP
- 第二部分 企业应用
- 第 8 章 数据库连接 JDBC
- 第 9 章 整合 MyBatis
- 第 10 章 事务
- 第 11 章 SpringMVC
- 第 12 章 远程服务
- 第 13 章 Spring 消息
4.1 自定义标签使用
在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于 Spring 的标准 bean 来配置,但配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙。一般的做法会用原生态的方式去解析定义好的 XML 文件,然后转化为配置对象。这种方式当然可以解决所有问题,但实现起来比较繁琐,特别是在配置非常复杂的时候,解析工作是一个不得不考虑的负担。Spring 提供了可扩展 Schema 的支持,这是一个不错的折中方案,扩展 Spring 自定义标签配置大致需要以下几个步骤(前提是要把 Spring 的 Core 包加入项目中)。
创建一个需要扩展的组件。
定义一个 XSD 文件描述组件内容。
创建一个文件,实现 BeanDefinitionParser 接口,用来解析 XSD 文件中的定义和组件定义。
创建一个 Handler 文件,扩展自 NamespaceHandlerSupport,目的是将组件注册到 Spring 容器。
编写 Spring.handlers 和 Spring.schemas 文件。
现在我们就按照上面的步骤带领读者一步步地体验自定义标签的过程。
(1)首先我们创建一个普通的 POJO,这个 POJO 没有任何特别之处,只是用来接收配置文件。
package test.customtag;
public class User {
private String userName;
private String email;
//省略 set/get 方法
}
(2)定义一个 XSD 文件描述组件内容。
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.lexueba.com/schema/user"
xmlns:tns="http://www.lexueba.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>
在上面的 XSD 文件中描述了一个新的 targetNamespace,并在这个空间中定义了一个 name 为 user 的 element,user 有 3 个属性 id、userName 和 email,其中 email 的类型为 string。这 3 个类主要用于验证 Spring 配置文件中自定义格式。XSD 文件是 XML DTD 的替代者,使用 XML Schema 语言进行编写,这里对 XSD Schema 不做太多解释,有兴趣的读者可以参考相关的资料。
(3)创建一个文件,实现 BeanDefinitionParser 接口,用来解析 XSD 文件中的定义和组件定义。
package test.customtag;
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 UserBeanDefinitionParser 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)创建一个 Handler 文件,扩展自 NamespaceHandlerSupport,目的是将组件注册到 Spring 容器。
package test.customtag;
import org.Springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
}
}
以上代码很简单,无非是当遇到自定义标签<user:aaa 这样类似于以 user 开头的元素,就会把这个元素扔给对应的 UserBeanDefinitionParser 去解析。
(5)编写 Spring.handlers 和 Spring.schemas 文件,默认位置是在工程的/META-INF/文件夹下,当然,你可以通过 Spring 的扩展或者修改源码的方式改变路径。
Spring.handlers。
http\://www.lexueba.com/schema/user=test.customtag.MyNamespaceHandler
Spring.schemas。
http\://www.lexueba.com/schema/user.xsd=META-INF/Spring-test.xsd
到这里,自定义的配置就结束了,而 Spring 加载自定义的大致流程是遇到自定义标签然后就去 Spring.handlers 和 Spring.schemas 中去找对应的 handler 和 XSD,默认位置是/META-INF/下,进而有找到对应的 handler 以及解析元素的 Parser,从而完成了整个自定义元素的解析,也就是说自定义与 Spring 中默认的标准配置不同在于 Spring 将自定义标签解析的工作委托给了用户去实现。
(6)创建测试配置文件,在配置文件中引入对应的命名空间以及 XSD 后,便可以直接使用自定义标签了。
<beans xmlns="http://www.Springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:myname="http://www.lexueba.com/schema/user"
xsi:schemaLocation="http://www.Springframework.org/schema/beans http://www.
Springframework.org/schema/beans/Spring-beans-2.0.xsd
http://www.lexueba.com/schema/user http://www.lexueba.com/schema/user.xsd">
<myname:user id="testbean" userName="aaa" email="bbb"/>
</beans>
(7)测试。
public static void main(String[] args) {
ApplicationContext bf = new ClassPathXmlApplicationContext ("test/customtag/
test.xml");
User user=(User) bf.getBean("testbean");
System.out.println(user.getUserName()+","+user.getEmail());
}
不出意外的话,你应该看到了我们期待的结果,控制台上打印出了:
aaa,bbb
在上面的例子中,我们实现了通过自定义标签实现了通过属性的方式将 user 类型的 Bean 赋值,在 Spring 中自定义标签非常常用,例如我们熟知的事务标签:tx(<tx:annotation-driven>)。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论