Spring中自定义Schema扩展机制
一、前言
Spring 为基于 XML 构建的应用提供了一种扩展机制,用于定义和配置 Bean。 它允许使用者编写自定义的 XML bean 解析器,并将解析器本身以及最终定义的 Bean 集成到 Spring IOC 容器中。
二、自定义 XML Schema 扩展
为了搞懂 Spring 的 XML 扩展机制,最直接的方式便是实现一个自定义的扩展。实现的步骤也为四步:
- 编写一个 XML schema 文件描述的你节点元素。
- 编写一个 NamespaceHandler 的实现类
- 编写一个或者多个 BeanDefinitionParser 的实现 (关键步骤).
- 注册上述的 schema 和 handler
1. 编写 resources/META-INF/Car.xsd
1 <?xml version="1.0" encoding="UTF-8"?>
2 <xsd:schema xmlns="http://www.mycompany.com/schema/my"
3 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
4 xmlns:beans="http://www.springframework.org/schema/beans"
5 targetNamespace="http://www.mycompany.com/schema/my1"
6 elementFormDefault="qualified"
7 attributeFormDefault="unqualified">
8
9 <xsd:import namespace="http://www.springframework.org/schema/beans"/>
10
11 <xsd:element name="car">
12 <xsd:complexType>
13 <xsd:complexContent>
14 <xsd:extension base="beans:identifiedType">
15 <xsd:attribute name="brand" type="xsd:string" use="required"/>
16 <xsd:attribute name="engine" type="xsd:float"/>
17 <xsd:attribute name="horsePower" type="xsd:int"/>
18 </xsd:extension>
19 </xsd:complexContent>
20 </xsd:complexType>
21 </xsd:element>
22 </xsd:schema>
这里,targetNamespace对Car标签很重要,比如说注册一个bean
1 <my1:car id="magic" brand="Magic" engine="4.5" horsePower="605" />
2. 编写 CarNamespaceHandler
1 public class CarNamespaceHandler extends NamespaceHandlerSupport {
2
3 @Override
4 public void init() {
5 //遇到car元素的时候交给CarBeanDefinitionParser来解析
6 registerBeanDefinitionParser("car", new CarBeanDefinitionParser());
7
8 }
9
10 }
编写的NamespaceHandler 来帮助 Spring 解析 XML 中不同命名空间的各类元素。不同的命名空间需要不同的 NamespaceHandler 来处理。使用 CarNamespaceHandler 来解析 car 的命名空间。
1 public interface NamespaceHandler {
2 void init();
3 BeanDefinition parse(Element element, ParserContext parserContext);
4 BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition, ParserContext parserContext);
5 }
CarNamespaceHandler 继承 NamespaceHandlerSupport 抽象类,NamespaceHandlerSupport 抽象类实现了 NamespaceHandler 接口,并实现了parse()和decorate()方法,在CarNamespaceHandler 类中实现 NamespaceHandler 接口的init()方法,注册 BeanDefinitionParser 来完成解析节点以及注册 Bean 的工作。
3. 编写 CarBeanDefinitionParser
BeanDefinitionParser 是最为关键的一环。每一个 BeanDefinitionParser 实现类都负责一个映射,将一个 XML 节点解析成 IOC 容器中的一个实体类。
1 public class CarBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
2
3 @Override
4 protected Class<?> getBeanClass(Element element) {
5 //car元素对应Car对象类型
6 return Car.class;
7 }
8
9 @Override
10 protected void doParse(Element element, BeanDefinitionBuilder builder) {
11
12 String brand = element.getAttribute("brand");
13 String engine = element.getAttribute("engine");
14 String hp = element.getAttribute("horsePower");
15
16 //把对应的属性设置到bean中
17 if(StringUtils.hasText(brand))
18 builder.addPropertyValue("brand", brand);
19
20 if(StringUtils.hasText(engine))
21 builder.addPropertyValue("engine", engine);
22
23 if(StringUtils.hasText(hp))
24 builder.addPropertyValue("horsePower", hp);
25
26 }
27 }
parse() 方法会解析一个个 XML 中的元素,使用 RootBeanDefinition 组装成对象,并最终通过 parserContext 注册到 IOC 容器中。
至此,我们便完成了 XML 文件中定义的对象到 IOC 容器的映射。
4. 注册 schema 和 handler
最后一步还需要通知 Spring,告知其自定义 schema 的所在之处以及对应的处理器。
resources/META-INF/spring.handlers
1 http\://www.mycompany.com/schema/my1=spring.xml.ext.schema.CarNamespaceHandler
resources/META-INF/spring.schemas
1 http\://www.mycompany.com/schema/my1.xsd=META-INF/car.xsd
一个自定义的 XML schema 便扩展完成了,接下来验证一下自定义Schema扩展。
三、验证扩展
定义好Spring的bean配置文件
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:my1="http://www.mycompany.com/schema/my1"
5 xsi:schemaLocation="
6 http://www.springframework.org/schema/beans
7 http://www.springframework.org/schema/beans/spring-beans.xsd
8 http://www.mycompany.com/schema/my1
9 http://www.mycompany.com/schema/my1.xsd">
10
11 <my1:car id="magic" brand="Magic" engine="4.5" horsePower="605" />
12
13 </beans>
编写测试方法
1 @RunWith(SpringJUnit4ClassRunner.class)
2 @ContextConfiguration(locations = { "classpath:app.xml" })
3 public class SchemaTest {
4
5 @Autowired
6 @Qualifier("magic")
7 private Car car;
8
9 @Test
10 public void propertyTest() {
11 assertNotNull(car);
12
13 String brand = car.getBrand();
14 float engine = car.getEngine();
15 int horsePower = car.getHorsePower();
16
17 System.out.println("==============================");
18 assertEquals("Brand incorrect.Should be Magic.", "Magic", brand);
19 assertEquals("Engine incorrect.Should be 4.5L.", 4.5, engine, 0.000001);
20 assertEquals("HorsePower incorrect.Should be 605hp.", 605, horsePower);
21
22 }
23 }
控制台输出无异常,断言成功。

Spring中自定义Schema扩展机制的更多相关文章
- 聊聊 Spring 的 XML Schema 扩展机制的使用方式
前言 在当前Java生态,Spring算的上是最核心的框架,所有的开发组件想要得到大范围更便捷的使用,都要和Spring进行整合,比如我们熟知的Mybatis.Dubbo等,以及内部封装的各类组件包括 ...
- 缘起 Dubbo ,讲讲 Spring XML Schema 扩展机制
背景 在 Dubbo 中,可以使用 XML 配置相关信息,也可以用来引入服务或者导出服务.配置完成,启动工程,Spring 会读取配置文件,生成注入 相关 Bean.那 Dubbo 如何实现自定义 X ...
- 6.2 dubbo在spring中自定义xml标签源码解析
在6.1 如何在spring中自定义xml标签中我们看到了在spring中自定义xml标签的方式.dubbo也是这样来实现的. 一 META_INF/dubbo.xsd 比较长,只列出<dubb ...
- 6.1 如何在spring中自定义xml标签
dubbo自定义了很多xml标签,例如<dubbo:application>,那么这些自定义标签是怎么与spring结合起来的呢?我们先看一个简单的例子. 一 编写模型类 package ...
- Spring中ApplicationContext加载机制和配置初始化
Spring中ApplicationContext加载机制. 加载器目前有两种选择:ContextLoaderListener和ContextLoaderServlet. ...
- Spring Schema扩展机制
1:概述 Spring2.0开始,Spring提供XML Schema可扩展机制,用户可以自定义XML Schema文件,并自定义 XML Bean解析器,集成到Spring IOC容器中. 2:步骤 ...
- day05 Spring中自定义注解的用处-之获取自定义的Servie
PS: 在RPC远程调用中,想要获取自定义的service的方法,就得自定义标签遍历拿到方法 PS:在spring中,两个最核心的 概念是aop和ioc,aop其实就是动态代理. ioc 就是解决对象 ...
- spring中自定义Event事件的使用和浅析
在我目前接触的项目中,用到了许多spring相关的技术,框架层面的spring.spring mvc就不说了,细节上的功能也用了不少,如schedule定时任务.Filter过滤器. intercep ...
- spring中的事务传播机制
1.事务的实现思想 在spring中要想某个方法具有事务,只要在方法前加一个@Transactional注解.然后spring就会利用aop思想,在这个方法执行前开启事务, 在方法执行后选择提交事务或 ...
随机推荐
- docker学习笔记(一)--ubunru18.04下面安装docker18.03
我是在本地安装的虚拟机,再搭建的环境,虚拟机的安装可以参考下面的博客: https://blog.csdn.net/u013142781/article/details/50529030 安装好了之后 ...
- 洛谷P1803——凌乱的yyy(贪心)
题目描述 现在各大oj上有n个比赛,每个比赛的开始.结束的时间点是知道的. yyy认为,参加越多的比赛,noip就能考的越好(假的) 所以,他想知道他最多能参加几个比赛. 由于yyy是蒟蒻,如果要参加 ...
- 猪齿鱼 SaaS 版效能平台发布
日前,猪齿鱼Choerodon全场景效能平台Saas版发布,提供体系化方法论和协作.测试.DevOps及容器工具,帮助企业拉通需求.设计.开发.部署.测试和运营流程,一站式提高管理效率和质量.从团队 ...
- 关于当前PHP脚本运行时系统信息相关函数
我们的 PHP 在执行的时候,其实可以获取到非常多的当前系统相关的信息.就像很多开源的 CMS 一般会在安装的时候来检测一些环境信息一样,这些信息都是可以方便地动态获取的. 脚本文件运行时的系统用户相 ...
- ecshop调用指定栏目下的文章的方法
打开 index.php 添加 fun函数一个,需放在<php与?>中间. /** * 获得指定栏目的文章列表. * @param int $cid 栏目ID * @param int $ ...
- Linux系列(10) - 命令搜索命令whereis与which
whereis 只能搜索系统命令,不能搜索自己凭空创建的普通文件 命令格式: whereis [命令名] 选项: -b:只查找可执行文件 -m:只查找帮助文件 which 搜索命令所在路径及别名:不是 ...
- Shell系列(14)- declare声明变量
declare声明变量类型 格式 declare [+/-] [选项] [变量名] 选项 -:给变量设定类型属性 +:取消变量的类型属性 -a :将变量声明为数组型 -i :将变量声明为整数型(int ...
- P4640-[BJWC2008]王之财宝【OGF,Lucas定理】
正题 题目链接:https://www.luogu.com.cn/problem/P4640 题目大意 \(n\)种物品,其中\(t\)种物品是有个数限制的,第\(i\)种限制为\(b_i\),求选出 ...
- JS返回一个字符串中长度最小的单词的长度
题目:编写一个方法,返回字符串中最小长度的单词的长度. var str = 'What a good day today!'; 1 //方法一 2 function returnString1(str ...
- Git学习笔记01-安装
首先,什么是git? git是开源的分布式系统,能够将团队的项目上传至git,供团队修改demo 第一步:安装好git(推荐淘宝镜像下载,地址https://npm.taobao.org/mirror ...