Spring中XMLschema扩展机制的原理是什么

Spring中XML schema扩展机制的原理是什么?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

在镇平等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站设计、成都做网站 网站设计制作按需网站策划,公司网站建设,企业网站建设,高端网站设计,成都营销网站建设,成都外贸网站制作,镇平网站建设费用合理。

自定义 XML 扩展

为了搞懂 Spring 的 XML 扩展机制,最直接的方式便是实现一个自定义的扩展。实现的步骤也非常简单,分为四步:

Spring中XML schema扩展机制的原理是什么

  • 编写一个 XML schema 文件描述的你节点元素。

  • 编写一个 NamespaceHandler 的实现类

  • 编写一个或者多个 BeanDefinitionParser 的实现 (关键步骤).

  • 注册上述的 schema 和 handler。

我们的目的便是想要实现一个 kirito XML schema,我们的项目中可以自定义 kirito.xml,在其中会以 kirito 为标签来定义不同的类,并在最终的测试代码中验证这些声明在 kirito.xml 的类是否被 Spring 成功加载。大概像这样,是不是和 dubbo.xml 的格式很像呢?

Spring中XML schema扩展机制的原理是什么

动手实现

有了明确的目标,我们逐步开展自己的工作。

1 编写kirito.xsd

resources/META-INF/kirito.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.cnkirito.moe/schema/kirito"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:beans="http://www.springframework.org/schema/beans"
   targetNamespace="http://www.cnkirito.moe/schema/kirito"> ①

 <xsd:import namespace="http://www.springframework.org/schema/beans"/>

 <xsd:element name="application"> ②
  <xsd:complexType>
   <xsd:complexContent>
    <xsd:extension base="beans:identifiedType">
     <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:extension>
   </xsd:complexContent>
  </xsd:complexType>
 </xsd:element>

 <xsd:element name="service"> ②
  <xsd:complexType>
   <xsd:complexContent>
    <xsd:extension base="beans:identifiedType">
     <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:extension>
   </xsd:complexContent>
  </xsd:complexType>
 </xsd:element>


</xsd:schema>

① 注意这里的 targetNamespace="http://www.cnkirito.moe/schema/kirito" 这便是之后 kirito 标签的关键点。

② kirito.xsd 定义了两个元素: application 和 service,出于简单考虑,都只有一个 name 字段。

schema 的意义在于它可以和 eclipse/IDEA 这样智能化的集成开发环境形成很好的搭配,在编辑 XML 的过程中,用户可以获得告警和提示。 如果配置得当,可以使用自动完成功能让用户在事先定义好的枚举类型中进行选择。

2 编写KiritoNamespaceHandler

public class KiritoNamespaceHandler extends NamespaceHandlerSupport {

 @Override
 public void init() {
  super.registerBeanDefinitionParser("application", new KiritoBeanDefinitionParser(ApplicationConfig.class));
  super.registerBeanDefinitionParser("service", new KiritoBeanDefinitionParser(ServiceBean.class));
 }
}

完成 schema 之后,还需要一个 NamespaceHandler 来帮助 Spring 解析 XML 中不同命名空间的各类元素。

<kirito:application name="kirito"/>
<dubbo:application name="dubbo"/>
<motan:application name="motan"/>

不同的命名空间需要不同的 NamespaceHandler 来处理,在今天的示例中,我们使用 KiritoNamespaceHandler 来解析 kirito 命名空间。KiritoNamespaceHandler 继承自 NamespaceHandlerSupport 类,并在其 init() 方法中注册了两个 BeanDefinitionParser ,用于解析 kirito 命名空间/kirito.xsd 约束中定义的两个元素:application,service。BeanDefinitionParser 是下一步的主角,我们暂且跳过,将重心放在父类 NamespaceHandlerSupport 之上。

public interface NamespaceHandler {
 void init();
 BeanDefinition parse(Element element, ParserContext parserContext);
 BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
}

NamespaceHandlerSupport 是 NamespaceHandler 命名空间处理器的抽象实现,我粗略看了NamespaceHandler 的几个实现类,parse 和 decorate 方法可以完成元素节点的组装并通过 ParserContext 注册到 Ioc 容器中,但实际我们并没有调用这两个方法,而是通过 init() 方法注册 BeanDefinitionParser 来完成解析节点以及注册 Bean 的工作,所以对于 NamespaceHandler,我们主要关心 init 中注册的两个 BeanDefinitionParser 即可。

3 编写KiritoBeanDefinitionParser

在文章开始我们便标记到 BeanDefinitionParser 是最为关键的一环,每一个 BeanDefinitionParser 实现类都负责一个映射,将一个 XML 节点解析成 IOC 容器中的一个实体类。

public class KiritoBeanDefinitionParser implements BeanDefinitionParser {

 private final Class<?> beanClass;

 public KiritoBeanDefinitionParser(Class<?> beanClass) {
  this.beanClass = beanClass;
 }

 private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass) {
  RootBeanDefinition beanDefinition = new RootBeanDefinition();
  beanDefinition.setBeanClass(beanClass);
  beanDefinition.setLazyInit(false);
  String name = element.getAttribute("name");
  beanDefinition.getPropertyValues().addPropertyValue("name", name);
  parserContext.getRegistry().registerBeanDefinition(name, beanDefinition);
  return beanDefinition;
 }

 @Override
 public BeanDefinition parse(Element element, ParserContext parserContext) {
  return parse(element, parserContext, beanClass);
 }
}

由于我们的实体类是非常简单的,所以不存在很复杂的解析代码,而实际项目中,往往需要大量的解析步骤。parse 方法会解析一个个 XML 中的元素,使用 RootBeanDefinition 组装成对象,并最终通过 parserContext 注册到 IOC 容器中。

至此,我们便完成了 XML 文件中定义的对象到 IOC 容器的映射。

4 注册schema和handler

最后一步还需要通知 Spring,告知其自定义 schema 的所在之处以及对应的处理器。

resources/META-INF/spring.handlers

http\://www.cnkirito.moe/schema/kirito=moe.cnkirito.sample.xsd.KiritoNamespaceHandler

resources/META-INF/spring.schemas

http\://www.cnkirito.moe/schema/kirito/kirito.xsd=META-INF/kirito.xsd

没有太多可以说的,需要遵守 Spring 的约定。

至此一个自定义的 XML schema 便扩展完成了,随后来验证一下。

验证扩展

我们首先定义好 kirito.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:kirito="http://www.cnkirito.moe/schema/kirito"
  xsi:schemaLocation=" http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.cnkirito.moe/schema/kirito
        http://www.cnkirito.moe/schema/kirito/kirito.xsd">

 <kirito:application name="kirito-demo-application"/>

 <kirito:service name="kirito-demo-service"/>

</beans>

使用 Spring 去加载它,并验证 IOC 容器中是否存在注册成功的 Bean。

@SpringBootApplication
@ImportResource(locations = {"classpath:kirito.xml"})
public class XmlSchemaAuthoringSampleApplication {

 public static void main(String[] args) {
  ConfigurableApplicationContext applicationContext = SpringApplication.run(XmlSchemaAuthoringSampleApplication.class, args);
  ServiceBean serviceBean = applicationContext.getBean(ServiceBean.class);
  System.out.println(serviceBean.getName());
  ApplicationConfig applicationConfig = applicationContext.getBean(ApplicationConfig.class);
  System.out.println(applicationConfig.getName());
 }
}

观察控制台的输出:

kirito-demo-service
kirito-demo-application

一个基础的基于 XML schema 的扩展便完成了。

Dubbo中的XML schema扩展

最后我们以 Dubbo 为例,看看一个成熟的 XML schema 扩展是如何被应用的。

Spring中XML schema扩展机制的原理是什么

看完上述内容,你们掌握Spring中XML schema扩展机制的原理是什么的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注创新互联行业资讯频道,感谢各位的阅读!

分享文章:Spring中XMLschema扩展机制的原理是什么
分享路径:https://www.cdcxhl.com/article22/pdecjc.html

成都网站建设公司_创新互联,为您提供虚拟主机移动网站建设企业建站ChatGPT网站内链Google

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

h5响应式网站建设