缘起 Dubbo ,讲讲 Spring XML Schema 扩展机制
背景
在 Dubbo 中,可以使用 XML 配置相关信息,也可以用来引入服务或者导出服务。配置完成,启动工程,Spring 会读取配置文件,生成注入 相关 Bean。那 Dubbo 如何实现自定义 XML 被 Spring 加载读取?
Spring XML Schema 扩展机制。从 Spring 2.0 开始,Spring 开始提供了一种基于 XML Schema 格式扩展机制,用于定义和配置 bean。
Spring XML Schema 扩展机制
实现 Spring XML Schema 扩展,其实非常简单,只需要完成下面四步。
- 创建 XML Schema 文件,由于该文件后缀名为 xsd,下面称为 XSD 文件。
- 编写实现一个或多个
BeanDefinitionParser
。 - 编写
NamespaceHandler
实现类。 - 注册
NamespaceHandler
以及 XSD 文件。
我们按照以上步骤,最终完整 Spring 解析如下配置。
<?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:demo="http://www.test.com/demo"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.test.com/demo http://www.test.com/demo/demo.xsd">
<demo:application name="test" id="test"/>
</beans>
创建 XSD 文件
XSD 文件,主要用来定义 XML 格式,用来验证 XML 合法性。在 IDE 中,导入 XSD 文件,编辑 XML 文件可以获得相关提示。
下面我们生成一个 XSD 文件。
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.test.com/demo"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.test.com/demo"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<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:schema>
上面 XSD 文件中 http://www.test.com/demo 为自定义命名空间地址,下面将会使用到。
实现 BeanDefinitionParser
这里实现 BeanDefinitionParser,真正解析 XML 动作在这里完成。
由于上面的例子比较简单,我们可以直接继承 Spring 提供的抽象类 AbstractSingleBeanDefinitionParser
,然后实现相关方法就可以了。
public class DemoBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
/**
* 返回最会需要注入 Spring Bean 的类型
* @param element
* @return
*/
@Override
protected Class<?> getBeanClass(Element element) {
return DemoApplication.class;
}
/***
* 这个方法完成真正解析动作
* @param element
* @param builder
*/
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
String name=element.getAttribute("name");
builder.addPropertyValue("name",name);
}
}
当然也可以直接实现 BeanDefinitionParser,这样更加灵活,但是这样相比于上面这个就比较复杂了。
public class BeanApplicationDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
String name=element.getAttribute("name");
// Bean 定义,最后根据这个生产 Bean
RootBeanDefinition rootBeanDefinition=new RootBeanDefinition();
rootBeanDefinition.setBeanClass(DemoApplication.class);
rootBeanDefinition.setLazyInit(false);
// 添加解析的属性
rootBeanDefinition.getPropertyValues().add("name",name);
// 将生成的 BeanDefinition 注册,少了这一步将会导致最后生成 Bean 时报错
parserContext.getRegistry().registerBeanDefinition("application",rootBeanDefinition);
return rootBeanDefinition;
}
}
实现 NamespaceHandler
这一步实现 NamespaceHandler,开发者自定义 NamespaceHandler 只要继承 NamespaceHandlerSupport
抽象类,实现 init
方法。在这个方法中注册上面一步实现 BeanDefinitionParser
。
public class DemoNameSpaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
// elementName 为命名空间
registerBeanDefinitionParser("application",new BeanApplicationDefinitionParser());
}
}
注册 XSD 以及 NamespaceHandler
这一步我们需要在 META-INF 中生成两个配置文件,分别为 spring.handlers
,spring.schemas
。
spring.schemas
指定 XSD 文件路径。
http\://www.test.com/demo/demo.xsd=com/spring/learning/xml/schemas/autoring/leanrn/demo.xsd
spring.handlers
指定 NamespaceHandler
完整类名,既包含前面的包名。
这里需要注意的是
:
需要进行转义
测试运行
首先我们生产 Spring 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:demo="http://www.test.com/demo"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.test.com/demo http://www.test.com/demo/demo.xsd">
<demo:application name="test" id="test"/>
</beans>
这里需要注意需要使用 XSD 文件中定义 http://www.test.com/demo
。
接着我们使用 SpringBoot ,导入 XML 文件,然后运行。
@SpringBootApplication
@ImportResource(locations = {"classpath:applicationContext.xml"})
public class XmlSchemaApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(XmlSchemaApplication.class, args);
DemoApplication demoApplication=applicationContext.getBean(DemoApplication.class);
System.out.println("application name is "+demoApplication.getName());
}
}
输出结果为:
application name is test
Spring XML 扩展机制源码研究
这里我们主要研究自定义 XML 扩展文件如何被 Spring 加载。
Spring 启动过程中会通过 BeanDefinitionDocumentReader
读取 beans 标签里面所有配置,这个过程将会通过 BeanDefinitionParserDelegate#parseCustomElement
解析自定义元素。
上面解析过程可以获得自定义 NamespaceHandler
,然后调用 parse
方法解析。
接着我们查看 NamespaceHandlerResolver#resolve
方法,查看如何获取自定义 NamespaceHandler
。
在这个方法中,主要是从 handlerMappings
缓存中获取 NamespaceHandler
。而该缓存来源于 getHandlerMappings
方法,这个方法将会加载我们上面自定义 spring.handlers
文件。
看完 Spring 加载 NamespaceHandler
过程,下面我们查看最重要 BeanDefinition
如何生成。
上面已经讲到 Spring 会使用 NamespaceHandler.parse
解析,由于我们继承了 NamespaceHandlerSupport
,查看里面具体实现。
获取到 BeanDefinition 会将其注册到容器中,然后会通过 BeanDefinition
生成 Bean。这个生成过程不属于本章节内容,所以不再概述,感兴趣同学可以自行搜索。
Dubbo XML Schema 扩展实现
最后我们查看 Dubbo XML Schema 扩展如何实现。
可以看到 Dubbo XML Schema 扩展刚好对应 Spring 四个标准的步骤。
总结
最后用一张图片总结全文内容。
帮助文档
xsd-custom-registration
Spring中的XML schema扩展机制
缘起 Dubbo ,讲讲 Spring XML Schema 扩展机制的更多相关文章
- 聊聊 Spring 的 XML Schema 扩展机制的使用方式
前言 在当前Java生态,Spring算的上是最核心的框架,所有的开发组件想要得到大范围更便捷的使用,都要和Spring进行整合,比如我们熟知的Mybatis.Dubbo等,以及内部封装的各类组件包括 ...
- 聊聊spring的那些扩展机制
1.背景 慎入:本文将会有大量代码出入. 在看一些框架源码的时候,可以看见他们很多都会和Spring去做结合.举个例子dubbo的配置: 很多人其实配置了也就配置了,没有去过多的思考:为什么这么配置s ...
- dubbo源码之一——xml schema扩展
dubbo源码版本:2.5.4 dubbo-parent |----dubbo-config |----dubbo-config-api |----com.alibaba.dubbo.config.* ...
- Spring中自定义Schema扩展机制
一.前言 Spring 为基于 XML 构建的应用提供了一种扩展机制,用于定义和配置 Bean. 它允许使用者编写自定义的 XML bean 解析器,并将解析器本身以及最终定义的 Bean 集成到 S ...
- Spring Schema扩展机制
1:概述 Spring2.0开始,Spring提供XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义 XML Bean解析器,集成到Spring IOC容器中. 2:步骤 ...
- dubbo源码—dubbo自定义spring xml标签
dubbo为了和spring更好的集成,提供了一些xml配置标签,也就是自定义标签 spring自定义标签 spring自定义标签的方式如下: 设计配置属性和JavaBean 编写xsd文件,校验xm ...
- 集成Dubbo服务(Spring)
Dubbo是什么? Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点. Dubbo[]是 ...
- 【Dubbo实战】 Dubbo+Zookeeper+Spring整合应用篇-Dubbo基于Zookeeper实现分布式服务(转)
Dubbo与Zookeeper.Spring整合使用 Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spri ...
- Dubbo+Zookeeper+Spring整合应用篇-Dubbo基于Zookeeper实现分布式服务(转)
Dubbo与Zookeeper.Spring整合使用 Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spri ...
随机推荐
- PHP开发人员对JAVA的WEB开发入门(初版-基础知识)
最近准备对其他部门PHP开发的童鞋做一个对JAVA的培训.知己知彼,百战不殆,我要先了解点PHP,才能确认他们的基础,达到好的授课效果. PHP(原始为Personal Home Page的缩写,后正 ...
- JavaScript操作数据库JS操作Access数据库
avaScript操作数据库JS操作Access数据库,跟其他语言操作差不多,总结了一下习惯代码,仅供参考学习.现在在F盘有文件abc.mdf,表名为Student,一共2个字段,Id数字类型主键,s ...
- [转]Doing more with Outlook filter and SQL DASL syntax
本文转自:https://blogs.msdn.microsoft.com/andrewdelin/2005/05/10/doing-more-with-outlook-filter-and-sql- ...
- 第三方库Mantle的源码解析
Mantle是一个用于简化Cocoa或Cocoa Touch程序中model层的第三方库.通常我们的应该中都会定义大量的model来表示各种数据结构,而这些model的初始化和编码解码都需要写大量的代 ...
- Java web实现原理
说明 最近在看一本java web和tomcat技术介绍的书籍.故此,希望通过文字总结的方式总结自己学习所获,本篇主要介绍java实现web基本的信息浏览的方法原理. web的本质 由于技术能力有限, ...
- 一文解读ITIL (转)
首先声明自己不是ITIL方面的专家,特别是具体的规范细节,后面论述如有不当,请指正.但我为什么会提起它?主要是因为它和运维(IT服务管理)相关性太大了.早起的运维完全就是以ITIL来蓝本构建的,在当时 ...
- 成功安装mysql后,为何服务管理器里找不到MYSQL服务名【转】
解决方案:(参考以下命令) 1.打开cmd,切换到mysql的bin目录下 2. D:\Program Files\MySQL5.1\bin>mysqld.exe -install Servic ...
- 3. 海思Hi3519A MPP从入门到精通(三 视频输入)
视频输入(VI)模块实现的功能:通过 MIPI Rx(含 MIPI 接口.LVDS 接口和 HISPI 接 口),SLVS-EC,BT.1120,BT.656,BT.601,DC 等接口接收视频数据. ...
- arm-linux-gcc-4.5.1安装方法
写在前面 之前写了一篇arm-linux-gcc-5.4.0的安装方法,但是后来发现5.4.0这个版本可能有些太新了,所以又找了这个4.5.1版本(低版本),由FriendlyARM(友善之臂)提供, ...
- 一次shell脚本小事故,从中学习排错过程-软件测试
一次shell脚本小事故,从中学习排错过程 事出,童鞋使用shell脚本搭建测试环境的过称中..... 配置环境变量文件:/etc/profile(用于升级JDK或其他) 手动编辑方法:vi /etc ...