spring中的自定义标签
某些情况下,为了给业务系统提供可配置化支持,我们一般会用原生态的方式去解析定义好的XML文件,然后转化为配置对象。这种方式对于简单、单一的配置文件,或者是XML配置格式固定的配置文件,还是比较容易处理的。但是对于一些复杂的、对可扩展性、灵活性要求比较高的场景,使用这种方式去验证、解析就会比较麻烦了。针对这种情况,Spring提供了对用户扩展Schema的支持,这样就可以使用Spring已有的验证、解析工具进行自定义标签的处理了。
扩展Spring自定义标签配置还是比较简单的,大致需要以下几个步骤:
- 创建一个需要扩展的组件类
- 定义一个XSD文件,描述组件内容
- 创建一个类,实现BeanDefinitionParser接口,用来解析XSD文件中的各种定义以及组件定义
- 创建一个Handler类,并继承NamespaceHandlerSupport类,目的是将组件注册到Spring容器
- 编写spring.schemas和spring.handlers文件分别指定parser与handler,spring默认会通过这两个文件找到BeanDefinitionParser与NamespaceHandlerSupport
下边通过一个简单的示例来展示一下如何创建一个自定义的标签。
- 创建一个普通的POJO类
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; } }
- 定义一个XSD文件,用来描述组件内容
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/schema/user" xmlns:tns="http://www.example.org/schema/user" elementFormDefault="qualified"> <element name="user"> <complexType> <attribute name="id" type="string"></attribute> <attribute name="userName" type="string"></attribute> <attribute name="email" type="string"></attribute> </complexType> </element> </schema>
将XSD文件放在src/main/resources/META-INF下,名称为spring-test.xsd
- 创建一个类,实现BeanDefinitionParser接口,用来解析XSD文件中的各种定义和组件定义
public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser{ @Override protected Class<?> getBeanClass(Element element){ return User.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder bean){ String userName = element.getAttribute("userName"); String email = element.getAttribute("email"); if(StringUtils.hasText(userName)){ bean.addPropertyValue("userName", userName); } if(StringUtils.hasText(email)){ bean.addPropertyValue("email", email); } } }
- 创建一个Handler类,并继承NamesapceHandlerSupport,目的是将组件注册到Spring容器
public class MyNamespaceHandlerSupport extends NamespaceHandlerSupport{ @Override public void init() { registerBeanDefinitionParser("user", new UserBeanDefinitionParser()); } }
- 目前spring还无法加载我们这些自定义的东西,还需要让spring能够找到并加载我们自定义的东西,这个时候就要用到spring.handlers和spring.schemas文件,因为spring会默认查找src/main/resources/META-INF目录下的这两个文件,来检查是否有用户自定义的标签。
- spring.schemas
http\://www.example.org/schema/user.xsd=META-INF/spring-test.xsd
- spring.handlers
http\://www.example.org/schema/user=chapter04.MyNamespaceHandlerSupport
- spring.schemas
下边测试一下我们自定义的标签
- 创建测试的xml配置文件
<?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.example.org/schema/user" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.example.org/schema/user http://www.example.org/schema/user.xsd"> <myname:user id="testbean" userName="aaa" email="bbb" /> </beans>
这里的过程是,注意第四行“xmlns:myname”,当遇到myname开头的标签时,就会通过xmlns:myname="http://www.example.org/schema/user"找到该标签的命名空间为"http://www.example.org/schema/user",然后通过spring.handlers找到对应的该命名空间的handler为chapter04.MyNamespaceHandlerSupport,然后将名字为user的子标签交由UserBeanDefinitionParser对象进行处理。当需要对xml的元素进行验证时,通过第七行可以找到命名空间对应的xsd的名称http://www.example.org/schema/user.xsd,然后通过spring.schemas找到实际的xsd文件对应的位置META-INF/spring-test.xsd,通过spring-test.xsd对元素进行校验。
- 创建测试类
public class Test { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("beanFactoryTest.xml"); User user = (User)ac.getBean("testbean"); System.out.println(user.getUserName() + "," + user.getEmail()); } }

浙公网安备 33010602011771号