spring schema 扩展(NamespaceHandler,BeanDefinitionParser)
前言:Spring从2.0开始引入了一个新的机制用于扩展xml模式,我们就可以编写自定义的xml bean解析器然后集成到Spring IoC容器中(Spring不识别aop,mvc,这些标签都是通过本章要学习的内容,扩展标签)mvc:interceptors>mvc:interceptors>aop:config>aop:config>xml扩展大概有以下几个步
前言:Spring从2.0开始引入了一个新的机制用于扩展xml模式,我们就可以编写自定义的xml bean解析器然后集成到Spring IoC容器中(Spring不识别aop,mvc,这些标签都是通过本章要学习的内容,扩展标签)
<mvc:interceptors></mvc:interceptors>
<aop:config></aop:config>
xml扩展大概有以下几个步骤:
- 编写自定义类
- 编写xml schema来描述自定义元素
- 编写
NamespaceHandler
实现类 - 编写
BeanDefinitionParser
实现类 - 把以上组建注册到Spring
xml的schema约束:
先来说说xml文档的schema约束,它定义了xml文档的结构,内容和语法,包括元素和属性、关系的结构以及数据类型等等。有以下几点需要遵循:
1) 、所有的标签和属性都需要Schema来定义。(schema本身由w3c来定义)。
2)、所有的schema文件都需要以个ID,这里我们称之为 namespace,其值时一个url,通常是这个xml的xsd文件的地址。
3)、namespace值由 targetNamespace属性来指定
4)、引入一个schema约束,使用属性xmlns,属性值即为对应schema文件的命名空间 nameSpace。
5)、如果引入的schema非w3c组织定义的,必须指定schema文件的位置,schema文件的位置由 schemaLocation来指定。
6)、引入多个schema文件需要使用 别名。别名形式如下: xmlns:alias。
对于上述配置文件的详细解读:
1)、 声明默认的名称空间(xmlns="http://www.springframework.org/schema/beans")
2)、 声明XML Schema实例名称空间(http://www.w3.org/2001/XMLSchema-instance),并将xsi前缀与该名称空间绑定, 这样模式处理器就可以识别xsi:schemaLocation属性。XML Schema实例名称空间的前缀通常使用xsi
3)、 使 用xsi:schemaLocation属性指定名称空间(http://www.springframework.org/schema/beans) 和模式位置(http://www.springframework.org/schema/beans/spring-beans.xsd)相关。 XML Schema推荐标准中指出,xsi:schemaLocation属性可以在实例中的任何元素上使用,而不一定是根元素,不 过,xsi:schemaLocation属性必须出现在它要验证的任何元素和属性之前。
4)、使用别名引入多个schema文件。如上述 xmlns:mvc 、xmlns:tx 、xmlns:context等等。
编写自定义类
public class Miku { private String name; private int age; private char sex; }
编写自定义schema,文件名为:miku.xsd,路径为:classpath:META-INF/miku.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.mycompany.com/schema/my"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.mycompany.com/schema/my"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:element name="miku">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="age" type="xsd:int"/>
<xsd:attribute name="sex" type="xsd:char"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<miku :miku id="mymiku" name="hatsunemiku" age="16" sex="女"/>
编写NamespaceHandler
NamespaceHandler
用于解析我们自定义名字空间下的所有元素,目前我们要解析上面的miku:miku
元素。NamespaceHandler
里面只有3个方法:
init()
会在NamespaceHandler
初始化的时候被调用。BeanDefinition parse(Element, ParserContext)
- 当Spring遇到一个顶层元素的时候被调用。BeanDefinitionHolder decorate(Node, BeanDefinitionHolder, ParserContext)
- 当Spring遇到一个属性或嵌套元素的时候调用.
Spring提供了默认实现类NamespaceHandlerSupport
,我们只需在init的时候注册每个元素的解析器即可。
public class MikuNamespaceHandler extends NamespaceHandlerSupport { @Override public void init() { //遇到miku元素的时候交给MikuBeanDefinitionParser来解析 registerBeanDefinitionParser("miku", new MikuBeanDefinitionParser()); } }
编写BeanDefinitionParser
当遇到miku元素时,Spring会交给MikuBeanDefinitionParser来解析。MikuBeanDefinitionParser取出相应的属性然后设置到bean中。
public class MikuBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Override protected Class<?> getBeanClass(Element element) { //miku元素对应Miku对象类型 return Miku.class; } @Override protected void doParse(Element element, BeanDefinitionBuilder builder) { String name = element.getAttribute("name"); String age = element.getAttribute("age"); String sex = element.getAttribute("sex"); //把对应的属性设置到bean中 if(StringUtils.hasText(name)) builder.addPropertyValue("name", name); if(StringUtils.hasText(age)) builder.addPropertyValue("age", age); if(StringUtils.hasText(sex)) builder.addPropertyValue("sex", sex); } }
注册handler和schema(将组件串联起来)
namespaceHandler
和xsd文件放到2个指定的配置文件中,这2个文件都位于
META-INF
目录中。
META-INF/spring.handlers
spring.handlers
文件包含了xml schema uri和handler类的映射关系,比如:
http\://www.mycompany.com/schema/my=spring.xml.ext.schema.MikuNamespaceHandler
http\://www.mycompany.com/schema/my
命名空间的时候会交给MikuNamespaceHandler
来处理。
注意上面的冒号转义。 key部分必须和xsd文件中的targetNamespace
值保持一致。
META-INF/spring.schemas
这样bean装载就完成了,写个测试开心的试一下吧~更多推荐
所有评论(0)