在spring中存在默认标签与自定义标签两种,例如:<bean/>为默认标签,<tx:annotation-driven/>为自定义标签。spring自定义标签比较灵活,可以扩展自定义标签。
扩展spring自定义标签主要步骤:
创建一个需要扩展的组件;
定义一个XSD文件描述组件内容;
创建一个类,该类实现BeanDifinitionParser接口,主要用来解析XSD文件中的定义和组件的定义;
创建一个NamespaceHandler类,该类扩展NamespaceHandlerSupport,主要作用是将组件注册到spring的容器中;
编写spring.handlers和spring.schemas文件
现在用一个简单的实例来说明自定义标签的过程,该实例主要是通过自定义标签来获取对象。
(1)创建一个普通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;
}
}
(2)定义一个XSD文件描述组件内容,下面文件中targetNamespace表示文档中要定义的元素来自什么命名空间,elementFormDefault="qualified"表示要求xml文档的每一个元素都要有命名空间指定。该文件主要是定义一个user元素,该元素包含有id,username,email属性,其中属性类型为string。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.lw.com/schema/user"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.lw.com/schema/user"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:element name="user">
<xsd:complexType>
<xsd:attribute name="id" type="xsd:string"></xsd:attribute>
<xsd:attribute name="username" type="xsd:string"></xsd:attribute>
<xsd:attribute name="email" type="xsd:string"></xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
(3)创建一个UserBeanDifinitionParser类,该类实现BeanDifinitionParser接口,这个类主要用来解析XSD文件中定义元素
package com.lw.spring;
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中解析并提取对应的元素
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String username=element.getAttribute("username");
String email=element.getAttribute("email");
//将提取的数据放到BeanDefinitionBuilder中,待到完成所有bean的解析后统一注册到beanFactory中
if(StringUtils.hasText(username)){
builder.addPropertyValue("username", username);
}
if(StringUtils.hasText(email)){
builder.addPropertyValue("email", email);
}
}
}
(4)创建一个MyNamespaceHandler类,该类扩展NamespaceHandlerSupport,主要是将组件注册到Spring容器中。
package com.lw.spring;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
public class MyNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
}
}
(5)编写spring.handlers和spring.schemas文件,默认位置在工程的/META-INF/文件夹下,需要说明的是在测试过程中创建的META-INF文件夹必须放在classpath路径下,不然就会出现抛出错误,如果你使用的是eclipse创建的工程,可以在src在创建META-INF文件夹,并将spring.handlers和spring.schemas文件放入到该文件下。
spring.handlers该文件存放的是键值对,等号左边表示自定标签的命名空间,等号右边表示自定义处理器的类全名,主要是通过放射来获取该处理器实例对象。
http\://www.lw.com/schema/user=com.lw.spring.MyNamespaceHandler
spring.schemas该文件存放的也是键值对,等号左边表示自定义标签XSD的URL,等号右边表示自定义标签XSD在工程中的具体位置
http\://www.lw.com/schema/user.xsd=com/lw/spring/user.xsd
(6)创建配置文件,在配置文件中引入对应的命名空间及XSD后,就可以直接使用自定义标签。
<?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:user="http://www.lw.com/schema/user"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.lw.com/schema/user
http://www.lw.com/schema/user.xsd">
<user:user id="testuser" email="dad" username="ddd"></user:user>
</beans>
(7)建立一个测试类
package com.lw.spring;
import org.springframework.core.io.Resource;
public class TestSpring {
public static void main(String[] args) {
Resource resource=new ClassPathResource("applicationContext.xml");
XmlBeanFactory factory=new XmlBeanFactory(resource);
User mytest=(User) factory.getBean("testuser");
System.out.println(mytest.getUsername()+" , "+mytest.getEmail());
}
}
运行结果为:
ddd , dad
以上就是通过简单实例说明扩展Spring自定义标签的过程,若想了解更加自定义标签解析的详细内容,可以参考《Spring源码深度解析》这本书。
转载于:https://blog.51cto.com/11623217/1775150