spring 实现自定义 xml 标签

2017-01-06 18:40:33   最后更新: 2017-01-06 18:40:33   访问数量:387




此前我们介绍了通过 xml 配置生成 bean 的方法:

依赖构造器注入、注入属性装配 bean

你是否想过 xml 是如何解析的呢?我们是否可以自己定义一个 xml 标签,然后自己去处理用户对该标签的配置呢?

事实上,spring2.0 开始就提供了 schema 风格的 xml 扩展机制,允许我们添加额外的扩展标签,下面我们就来尝试一下

 

首先,我们需要对我们即将提供的标签进行声明和格式定义,spring 是通过解析我们提供的 xsd 文件来确定我们的自定义标签的格式的

xsd 文件是一种特殊的 xml 文件,spring 官方包中的提供了很多 xsd 文件的配置,我们可以去参考这些文件的定义方法来实现我们自己的定义

这里,我们来实现一个简单的标签 <techlogBean time="" name=""/>,来创建一个 bean

 

<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://techlog.cn/test.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" targetNamespace="http://techlog.cn/test.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.springframework.org/schema/beans" /> <xsd:element name="techlogBean"> <xsd:complexType> <xsd:complexContent> <xsd:extension base="beans:identifiedType"> <xsd:attribute name="time" type="xsd:int" use="required" /> <xsd:attribute name="name" type="xsd:string" use="required" /> </xsd:extension> </xsd:complexContent> </xsd:complexType> </xsd:element> </xsd:schema>

 

 

可以看到,这里我们使用 targetNamespace 来定义了我们的 xsd 命名空间,通过 xml 的 xmlns 属性传入这个命名空间即可使用我们的自定义标签了

 

NamespaceHandlerSupport 是 spring 提供的一个 abstract class,他只有一个 abstract 方法 -- init,在这个方法中,我们就可以去定义和注册我们的新标签了

在 NamespaceHandlerSupport 中,定义了三个用于注册我们的 xml 解析类的方法:

  1. protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser)
  2. protected final void registerBeanDefinitionDecorator(String elementName, BeanDefinitionDecorator dec)
  3. protected final void registerBeanDefinitionDecoratorForAttribute(String attrName, BeanDefinitionDecorator dec)

 

这里我们使用 registerBeanDefinitionParser 方法:

package com.techlog.test.testspring.xmlparser; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; /** * Created by techlog on 2017/1/6. */ public class TechlogNameSpaceHandler extends NamespaceHandlerSupport { @Override public void init() { registerBeanDefinitionParser("techlogBean", new TechlogBeanDefinitionParser()); } }

 

 

接下来就需要来定义我们的解析类 TechlogBeanDefinitionParser 了:

package com.techlog.test.testspring.xmlparser; import com.techlog.test.testspring.service.TechlogService; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; /** * Created by techlog on 2017/1/6. */ public class TechlogBeanDefinitionParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element element, ParserContext parserContext) { RootBeanDefinition def = new RootBeanDefinition(); // 设置Bean Class def.setBeanClass(TechlogService.class); // 注册ID属性 String id = element.getAttribute("id"); BeanDefinitionHolder idHolder = new BeanDefinitionHolder(def, id); BeanDefinitionReaderUtils.registerBeanDefinition(idHolder, parserContext.getRegistry()); // 注册属性 String time = element.getAttribute("time"); String name = element.getAttribute("name"); BeanDefinitionHolder timeHolder = new BeanDefinitionHolder(def, time); BeanDefinitionHolder nameHolder = new BeanDefinitionHolder(def, name); BeanDefinitionReaderUtils.registerBeanDefinition(timeHolder, parserContext.getRegistry()); BeanDefinitionReaderUtils.registerBeanDefinition(nameHolder, parserContext.getRegistry()); def.getPropertyValues().addPropertyValue("time", time); def.getPropertyValues().addPropertyValue("name", name); return def; } }

 

我们指定了 bean 类,加载了自定义标签中的 id、time、name 三个属性

 

那么,spring 是如何发现我们项目中的 xsd 文件和 Handler 类的呢?

当然是需要我们去指定的,在 webapp 目录中创建 META-INF 目录,在该目录下创建 spring.handlers 与 spring.schemas 两个文件,这两个文件就是分别用来声明我们的 Handler 类和 xsd 文件位置的

 

spring.handlers

http\://techlog.cn/test.xsd=com.techlog.test.testspring.xmlparser.TechlogNameSpaceHandler

 

 

spring.schemas

http\://techlog.cn/test.xsd=META-INF/techlog.xsd

 

 

这样,我们就可以在我们的 xml 配置文件中使用 我们定义的 techlogBean 标签了

 

spring源码学习之:xml配置文件标签自定义 -- http://www.cnblogs.com/shangxiaofei/p/5788650.html

 






技术帖      xml      技术分享      java      spring      xsd      parser      schema      tag      attribute      属性     


京ICP备15018585号