经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
Spring XML Schema扩展机制的使用示例
来源:jb51  时间:2021/5/31 15:06:13  对本文有异议

前言

在当前Java生态,Spring算的上是最核心的框架,所有的开发组件想要得到大范围更便捷的使用,都要和Spring进行整合,比如我们熟知的Mybatis、Dubbo等,以及内部封装的各类组件包括Redis、MQ、配置中心等。

有了整合这一步,我们只需引入相应的jar,比如mybatis-spring,然后进行简单的配置后即可在Spring工程中使用Mybatis的功能,也正是由于这样的便捷性,导致很多时候我们没有对其进行深究。

XML Schema扩展

打开mybatis-spring、dubbo的源码会发现在META-INF目录下有两个文件(如下图所示),spring.handlers与spring.schemas,这两个文件就是XML Schema扩展的关键入口点。

XSD

XSD,XML Schema Definition,XML定义。

XML Schema定义XML文档的结构,XML Schema语言也称为XML定义,即XSD。

简单的说,XSD用于制定xml文件规范,包括xml中的元素(简单元素、复杂元素)、属性、以及属性类型及约束等。

Spring XML Schema扩展的第一步就是要定义一个xsd文件,比如spring-beans对应xsd文件为http://www.springframework.org/schema/beans/spring-beans.xsd,如下图:

为了简单介绍Spring XML Schema扩展实现,下面将一个简单例子(模拟一个简单的分布式id生成器,不会实现具体功能)进行说明,xsd定义如下(文件命名为DistributedId.xsd,在META-INF目录下):

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xsd:schema xmlns="http://www.hexup.com/schema/distributed-id"
  3. xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.hexup.com/schema/distributed-id">
  4.  
  5.  
  6. <xsd:element name="distributed-id">
  7. <xsd:complexType>
  8. <xsd:attribute name="id" type="xsd:string"></xsd:attribute>
  9. <xsd:attribute name="bizCode" type="xsd:string"></xsd:attribute>
  10. <xsd:attribute name="length" type="xsd:int"></xsd:attribute>
  11. </xsd:complexType>
  12. </xsd:element>
  13. </xsd:schema>

上述xsd文件里定义了一个复杂元素distributed-id,包含属性id,bizCode,length,形如:

  1. <distributed-id id="xxx" bizCode="xxx" length="xxx"></distributed-id>

注意:xmlns,即为xml namespace,xml命名空间,后面跟的http链接地址可以不存在,因为xsd会放在当前工程的META-INF下。

配置spring.handlers和spring.schemas

如下两张图所示,spring.schemas文件中用于说明xsd的文件路径,spring.schemas文件用于说明解析此类xsd定义的标签的处理类,下面会对处理类进行详细说明。

NameSpaceHandler与BeanDefinitionParser

定义类DistributedIdNamespaceHandler继承NamespaceHandlerSupport,init方法用于注册BeanDefinition解析器,也就是解析xml中对应标签为Spring Bean。

  1. public class DistributedIdNamespaceHandler extends NamespaceHandlerSupport {
  2.  
  3. @Override
  4. public void init() {
  5. registerBeanDefinitionParser("distributed-id", new DistributedIdParser());
  6. }
  7. }

同时要创建BeanDefinitionParser

  1. public class DistributedIdParser implements BeanDefinitionParser {
  2.  
  3.  
  4. @Override
  5. public BeanDefinition parse(Element element, ParserContext parserContext) {
  6. // 解析xml内的标签
  7. String bizCode = element.getAttribute("bizCode");
  8. int length = Integer.valueOf(element.getAttribute("length"));
  9. String id = element.getAttribute("id");
  10. // 创建DistributedIdFactoryBean bean
  11. BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
  12. builder.getRawBeanDefinition().setBeanClass(DistributedIdFactoryBean.class);
  13. builder.setScope(BeanDefinition.SCOPE_SINGLETON);
  14.  
  15. builder.addPropertyValue("bizCode", bizCode);
  16. builder.addPropertyValue("length", length);
  17.  
  18. BeanDefinition beanDefinition = builder.getBeanDefinition();
  19.  
  20. parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);
  21.  
  22. return beanDefinition;
  23. }
  24. }

其中DistributedIdFactoryBean实现FactoryBean接口用于创建DistributedIdComponent Bean,如下

  1. public class DistributedIdFactoryBean implements InitializingBean, FactoryBean<DistributedIdComponent> {
  2.  
  3. private String bizCode;
  4. private int length;
  5.  
  6. private DistributedIdComponent distributedIdComponent;
  7.  
  8. @Override
  9. public DistributedIdComponent getObject() throws Exception {
  10. return distributedIdComponent;
  11. }
  12.  
  13. @Override
  14. public Class<?> getObjectType() {
  15. return DistributedIdComponent.class;
  16. }
  17.  
  18. @Override
  19. public boolean isSingleton() {
  20. return false;
  21. }
  22.  
  23. @Override
  24. public void afterPropertiesSet() throws Exception {
  25. distributedIdComponent = new DistributedIdComponent(bizCode, length);
  26. }
  27.  
  28. public void setBizCode(String bizCode) {
  29. this.bizCode = bizCode;
  30. }
  31.  
  32. public void setLength(int length) {
  33. this.length = length;
  34. }
  35. }

目标Bean DistributedIdComponent如下:

  1. public class DistributedIdComponent {
  2. private String bizCode;
  3. private int length;
  4.  
  5. public DistributedIdComponent() {
  6.  
  7. }
  8.  
  9. public DistributedIdComponent(String bizCode, int length) {
  10. this.bizCode = bizCode;
  11. this.length = length;
  12. }
  13.  
  14. public String generateId() {
  15. System.out.println("mock generate id");
  16. return String.valueOf(System.currentTimeMillis()).substring(0, length);
  17. }
  18.  
  19. public String getBizCode() {
  20. return bizCode;
  21. }
  22.  
  23. public void setBizCode(String bizCode) {
  24. this.bizCode = bizCode;
  25. }
  26.  
  27. public int getLength() {
  28. return length;
  29. }
  30.  
  31. public void setLength(int length) {
  32. this.length = length;
  33. }
  34. }

使用

spring配置文件,spring-service.xml中配置distributed-id标签以及对应的属性值,如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:distributed-id="http://www.hexup.com/schema/distributed-id"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd http://www.hexup.com/schema/distributed-id http://www.hexup.com/schema/distributed-id.xsd">
  7.  
  8.  
  9. <distributed-id:distributed-id id="test" bizCode="test" length="8"></distributed-id:distributed-id>
  10. </beans>

运行容器验证:

  1. public class App {
  2. public static void main(String[] args) {
  3. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-service.xml");
  4. DistributedIdComponent bean = context.getBean(DistributedIdComponent.class);
  5.  
  6. String id = bean.generateId();
  7.  
  8. System.out.println("id:" + id);
  9. }
  10. }

总结

本文主要介绍了Spring XML Schema扩展机制的使用方法,大致步骤为定义XSD文件、配置spring.schemas、编码实现NameSpaceHanlder和BeanDefinitionParser实现类、配置spring.handlers。但未说明具体的实现原理,后续会有一篇文章详细介绍Spring源码是怎么实现扩展的,以及介绍为什么使用FactoryBean来创建具体的Bean等问题。

以上就是Spring XML Schema扩展机制的使用示例的详细内容,更多关于Spring XML Schema扩展机制的使用的资料请关注w3xue其它相关文章!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号