Spring XML Schema扩展机制的使用示例

前言

在当前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目录下):

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.hexup.com/schema/distributed-id"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.hexup.com/schema/distributed-id">

    <xsd:element name="distributed-id">
        <xsd:complexType>
            <xsd:attribute name="id" type="xsd:string"></xsd:attribute>
            <xsd:attribute name="bizCode" type="xsd:string"></xsd:attribute>
            <xsd:attribute name="length" type="xsd:int"></xsd:attribute>
        </xsd:complexType>
    </xsd:element>

</xsd:schema>

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

<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。

public class DistributedIdNamespaceHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("distributed-id", new DistributedIdParser());
    }
}

同时要创建BeanDefinitionParser

public class DistributedIdParser implements BeanDefinitionParser {

    @Override
    public BeanDefinition parse(Element element, ParserContext parserContext) {
        // 解析xml内的标签
        String bizCode = element.getAttribute("bizCode");
        int length = Integer.valueOf(element.getAttribute("length"));
        String id = element.getAttribute("id");

        // 创建DistributedIdFactoryBean bean
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();
        builder.getRawBeanDefinition().setBeanClass(DistributedIdFactoryBean.class);
        builder.setScope(BeanDefinition.SCOPE_SINGLETON);

        builder.addPropertyValue("bizCode", bizCode);
        builder.addPropertyValue("length", length);

        BeanDefinition beanDefinition = builder.getBeanDefinition();

        parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);

        return beanDefinition;
    }
}

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

public class DistributedIdFactoryBean implements InitializingBean, FactoryBean<DistributedIdComponent> {

    private String bizCode;
    private int length;

    private DistributedIdComponent distributedIdComponent;

    @Override
    public DistributedIdComponent getObject() throws Exception {
        return distributedIdComponent;
    }

    @Override
    public Class<?> getObjectType() {
        return DistributedIdComponent.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        distributedIdComponent = new DistributedIdComponent(bizCode, length);
    }

    public void setBizCode(String bizCode) {
        this.bizCode = bizCode;
    }

    public void setLength(int length) {
        this.length = length;
    }
}

目标Bean DistributedIdComponent如下:

public class DistributedIdComponent {
    private String bizCode;
    private int length;

    public DistributedIdComponent() {

    }

    public DistributedIdComponent(String bizCode, int length) {
        this.bizCode = bizCode;
        this.length = length;
    }

    public String generateId() {
        System.out.println("mock generate id");
        return String.valueOf(System.currentTimeMillis()).substring(0, length);
    }

    public String getBizCode() {
        return bizCode;
    }

    public void setBizCode(String bizCode) {
        this.bizCode = bizCode;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }
}

使用

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

<?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:distributed-id="http://www.hexup.com/schema/distributed-id"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.hexup.com/schema/distributed-id http://www.hexup.com/schema/distributed-id.xsd">

    <distributed-id:distributed-id id="test" bizCode="test" length="8"></distributed-id:distributed-id>
</beans>

运行容器验证:

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-service.xml");
        DistributedIdComponent bean = context.getBean(DistributedIdComponent.class);

        String id = bean.generateId();

        System.out.println("id:" + id);
    }
}

总结

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

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

(0)

相关推荐

  • SpringBoot整合Mybatis无法扫描xml文件的解决

    网上说是使用idea在SpringBoot整合Mybatis时候会扫描不到xml文件 1.将xml文件放在resources下 2.在application.properties中配置xml文件的扫面 补充知识:Springboot整合mybatis /*.xml路径URl does not exist问题 解决一: 在配置文件下 扫描不到 xml文件: 原来的文件: <bean id="sqlSessionFactory" class="org.mybatis.spr

  • 关于Spring自定义XML schema 扩展的问题(Spring面试高频题)

    引言 自从SpringBoot时代的到来,去除了Spring的各种繁琐的XML配置,让我们可以腾出双手以便于更加专注的搬砖.记得那时候刚学Spring的时候,每天被Spring的各种XMl配置文件折磨的不行,每引入一个新的框架,最担心的就是jar冲突.哪个配置文件又配的不对.配置文件没有起作用.所以每次搭建好一个项目就把配置文件用小笔记记录下来, 方便下次在整合项目的时候直接copy复制就好.下面我们就以Spring整合dubbo的事例看下 <beans xmlns:xsi="http:/

  • spring*.xml配置文件明文加密的实现

    说明:客户要求spring*.xml中Oracle/Redis/MongoDB的IP.端口.用户名.密码不能明文存放,接到需求的我,很无奈,但是还是的硬着头皮搞 系统架构:spring+mvc(Oracle是用jdbc自己封装的接口) 1.数据库配置文件加密 原xml配置 <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/

  • Spring中XML schema扩展机制的深入讲解

    前言 很久没有写关于 Spring 的文章了,最近在系统梳理 Dubbo 代码的过程中发现了 XML schema 这个被遗漏的知识点.由于工作中使用 SpringBoot 比较多的原因,几乎很少接触 XML,此文可以算做是亡羊补牢,另一方面,也为后续的 Dubbo 源码解析做个铺垫. XML schema 扩展机制是啥?从Spring2.0开始,Spring提供了XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义XML Bean解析器,并集成到Spring Ioc

  • Springboot启动扩展点超详细教程小结

    1.背景 Spring的核心思想就是容器,当容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片.Springboot更是封装了Spring,遵循约定大于配置,加上自动装配的机制.很多时候我们只要引用了一个依赖,几乎是零配置就能完成一个功能的装配. 我非常喜欢这种自动装配的机制,所以在自己开发中间件和公共依赖工具的时候也会用到这个特性.让使用者以最小的代价接入.想要把自动装配玩的转,就必须要了解spring对于bean的构造生命周期以及各个扩展接口.当然了解了bean

  • 如何扩展Spring Cache实现支持多级缓存

    为什么多级缓存 缓存的引入是现在大部分系统所必须考虑的 redis 作为常用中间件,虽然我们一般业务系统(毕竟业务量有限)不会遇到如下图 在随着 data-size 的增大和数据结构的复杂的造成性能下降,但网络 IO 消耗会成为整个调用链路中不可忽视的部分.尤其在 微服务架构中,一次调用往往会涉及多次调用 例如pig oauth2.0 的 client 认证 Caffeine 来自未来的本地内存缓存,性能比如常见的内存缓存实现性能高出不少详细对比. 综合所述:我们需要构建 L1 Caffeine

  • 使用maven开发springboot项目时pom.xml常用配置(推荐)

    如题,记录一些平常开发用的pom文件细节 1.使用parent父类引用,解决依赖版本号不确定时自动匹配的问题 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/>

  • SpringBoot配置logback.xml 多环境的操作步骤

    前提 logback日志文件要实现springboot多环境配置,不然每次都需要修改logback.xml里面的配置文件,所以很麻烦. 操作步骤 1.resource文件的内容结构如下: 2.配置application.yml spring: profiles: active: dev logging: config: classpath:logback-${spring.profiles.active}.xml 3.配置lockback-dev.xml 这个地方就可以实现自己的多环境日志配置了

  • 解决Spring boot整合mybatis,xml资源文件放置及路径配置问题

    网上各种解决方案,我试了好久,整合了几篇文章才凑出来,在这里分享一下,实在不想网友们在这里面绕圈子,毕竟,写代码的时间是愉快的,解决bug也是愉快的,但也是一直在bug里面绕圈子就不爽了. 亲自试验: 1) 我的mapper和xml是这样子放置的 2) 在.xml中namespace是这样的: 3) application.properties中mybatis.mapper-locations得这么配置到xml 4) 最后呢,你只要在pom.xml中build下这样配置 5) 按照我这种位置防止

  • Spring XML Schema扩展机制的使用示例

    前言 在当前Java生态,Spring算的上是最核心的框架,所有的开发组件想要得到大范围更便捷的使用,都要和Spring进行整合,比如我们熟知的Mybatis.Dubbo等,以及内部封装的各类组件包括Redis.MQ.配置中心等. 有了整合这一步,我们只需引入相应的jar,比如mybatis-spring,然后进行简单的配置后即可在Spring工程中使用Mybatis的功能,也正是由于这样的便捷性,导致很多时候我们没有对其进行深究. XML Schema扩展 打开mybatis-spring.d

  • SpringBoot之自定义Schema扩展方式

    目录 SpringBoot 自定义Schema扩展 1. 配置ServiceConfig属性 2. 编写XSD文件 3. 编写NamespaceHandler 4. 编写BeanDefinitionParser 5. 配置spring.handlers和spring.schemas 6. 配置spring的加载文件 7. 测试 Spring Schema扩展机制 1. 概述 2. 步骤 3. 示例如下 SpringBoot 自定义Schema扩展 最近在写RPC框架时,用到了自定义的xsd配置.

  • Spring是怎么扩展解析xml接口的

    目录 自定义Spring配置 BeanDefinitionParserDelegate DefaultNamespaceHandlerResolver NamespaceHandlerSupport implements NamespaceHandler BeanDefinitionParser ParserContext 自定义Spring配置 Java自定义Spring配置标签 BeanDefinitionParserDelegate 在DefaultBeanDefinitionDocume

  • Spring Cloud 中自定义外部化扩展机制原理及实战记录

    目录 自定义PropertySource 扩展PropertySourceLocator Spring.factories 编写controller测试 阶段性总结 SpringApplication.run PropertySourceBootstrapConfiguration.initialize ApplicationContextInitializer的理解和使用 创建一个TestApplicationContextInitializer 添加spi加载 Spring Cloud针对E

  • SpringMVC用XML方式实现AOP的方法示例

    1.首先创建web工程,之后导入Spring jar包,目录如下 2.文件代码 2.1AfterAdvice package com.niit.aop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; /* * 后置通知 * havingClass方法执行之后才执行. * 输出日记 * */ public class AfterAdvice implements After

  • Java的Spring框架下的AOP编程模式示例

    Spring框架的关键组件是面向方面编程(AOP)框架.面向方面的编程不仅打破程序逻辑分成不同的部分称为所谓的担忧.跨越多个点的应用程序的功能被称为横切关注点和这些横切关注点是从应用程序的业务逻辑概念上区分开来.还有像日志记录,审计,声明性事务,安全性和高速缓存等方面的各种常见的好例子 模块化的OOP中的关键单元是类,而在AOP中模块化的单元则是切面.依赖注入可以帮助你从对方解耦应用程序对象和AOP可以帮助你从他们影响的对象分离横切关注点. AOP是一样的编程语言如Perl,.NET,Java和

  • Java Spring开发环境搭建及简单入门示例教程

    本文实例讲述了Java Spring开发环境搭建及简单入门示例.分享给大家供大家参考,具体如下: 前言 虽然之前用过Spring,但是今天试着去搭建依然遇到了困难,而且上网找教程,很多写的是在web里使用Spring MVC的示例,官方文档里的getting start一开始就讲原理去了(可能打开的方法不对).没办法,好不容易实验成功了,记下来免得自己以后麻烦. 添加依赖包 进入spring官网,切换到projects下点击 spring framework.官网上写的是以maven依赖的形式写

  • Spring Boot 项目中使用Swagger2的示例

    本文介绍了Spring Boot 项目中使用Swagger2的示例,分享给大家,具体如下: 添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.2.2</version> </dependency&g

随机推荐