上一篇讲了Spring对默认标签的解析,Spring提供了很多属性,可以供开发者根据不同情况使用。绝大多数情况下,这些功能就已经足够了。但是,当用户有更特殊的需求,又或者很多公司自己实现的服务治理框架有一些自定义的需求是spring默认属性无法提供,或者是有更好得实现方式时,一种方式是像Spring一样用原生态的方式去解析定义好的XML文件,然后转化为配置对象,但这样实现起来比较复杂,还有一种方式就是通过Spring提供的可扩展Schema的支持,扩展自定义标签。

扩展自定义标签大致需要以下几个步骤:

1、创建一个需要扩展的组件

2、定义一个.xsd文件描述组件的内容

3、创建一个文件实现BeanDefinitionParser接口,用来解析xsd文件中的定义和组件的含义

4、创建一个handle文件,实现NamespaceHandleSupport,将组件和解析类注册到spring中

5、编写spring.handlers和spring.schemas

首先我们创建一个简单的pojo

package com.wuzhe.spring.test;

public class User {
private String userName; public String getUserName() {
return userName;
} public void setUserName(String userName) {
this.userName = userName;
}
}

第二步,新建一个xsd文件描述自定义的标签

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
xmlns="http://www.test.com/user"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.test.com/user"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:element name="user">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="userName" type="xsd:string" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>

这里定义了一个新的命名空间targetNamespace:http://www.test.com/user  并定义了自定义标签user的属性等信息。

接下来就需要定义解析自定义标签,将其转化为beanDefinition了。spring通过实现BeanDefinitionParser接口来解析自定义标签。

package com.wuzhe.spring.test;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.w3c.dom.Element; public class UserBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { @Override
protected Class getBeanClass (Element element){
return User.class;
} @Override
protected void doParse(Element element, BeanDefinitionBuilder bean){
String userName = element.getAttribute("userName");
bean.addPropertyValue("userName", userName);
}
}

这里只是简单地将自定义标签user中的userName属性,通过set注入到bean中。所以在beanDefinition添加了对应的PropertValue。

定义好了解析标签的过程,接下来就要在spring中注册这个标签和解析器的联系,这样spring在解析对应自定义标签时就知道用哪个解析器去解析它。

spring中通过扩展NamespaceHandlerSupport来实现这一功能。

package com.wuzhe.spring.test;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class Handler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("user", new UserBeanDefinitionParser());
}
}

最后我们需要编写spring.handlers和spring.schemas这两个文件。这两个文件的功能是在解析xml文件时,一旦遇到自定义标签,就会通过这两个文件找到对应的xsd文件和对应的Handler,然后在handler中注册的对应标签和解析器来解析自定义标签。

这两个文件的默认位置是在resource下的META-INF文件夹下

spring.handlers

http\://www.test.com/user=com.wuzhe.spring.test.Handler

spring.schemas

http\://www.test.com/user.xsd=META-INF/user.xsd

这里http后的\实际上是为了转义冒号的。另外需要特别注意xsd文件和handler类的路径一定不能错。

到这里自定义标签的准备工作就已经完成了。我们可以写一个测试demo

首先容器的配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cutesource="http://www.test.com/user"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.test.com/user http://www.test.com/user.xsd">
<cutesource:user id="testUser" userName="haha"/>
</beans>

这里使用了自定义的标签user,设置了属性userName的值

写个测试类

public class Main {
public static void main(String[] args) {
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("user.xml"));
User user = (User) beanFactory.getBean("testUser");
System.out.println(user.getUserName());
}
}

我们发现通过自定义标签的方式,成功获取了user实例,并且这个实例的userName属性被设置为了haha。说明我们的自定义配置生效了。

Spring源码学习(3)—— 自定义标签的更多相关文章

  1. Spring 源码学习(1) —— 自定义标签

    Spring 工作流程是先加载解析xml配置文件:配置文件中存在默认的标签,也可以自定义标签.解析默认标签调用: private void parseDefaultElement(Element el ...

  2. spring源码学习之默认标签的解析(一)

    继续spring源码的学习之路,现在越来越觉得这个真的很枯燥的,而且我觉得要是自己来看源码,真的看不下去,不是没有耐心,而是真的没有头绪,我觉得结合着书来看,还是很有必要的,最起码大致的流程是能够捋清 ...

  3. spring源码学习之默认标签的解析(二)

    这个是接着上一篇来写,主要是这章内容比较多,还是分开来写吧! 一.AbstractBeanDefinition属性介绍 XML中的所有的属性都可以在GenericBeanDefinition中找到对应 ...

  4. spring源码研究2 自定义标签实现及使用

    1.自定义标签实现及使用参考: http://blog.csdn.net/fighterandknight/article/details/50112701 1)创建一个需要扩展的组件 User.ja ...

  5. Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md

    写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...

  6. Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签

    写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...

  7. Spring源码学习

    Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...

  8. Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作

    写在前面 上文 Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件主要讲Spring容器创建时通过XmlBeanDefinitionReader读 ...

  9. Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点

    Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...

  10. spring源码学习之路---IOC初探(二)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...

随机推荐

  1. TCP/IP协议详解内容总结(怒喷一口老血)

    TCP/IP协议(本文源自外部链接) TCP/IP不是一个协议,而是一个协议族的统称.里面包括IP协议.IMCP协议.TCP协议. 这里有几个需要注意的知识点: 互联网地址:也就是IP地址,一般为网络 ...

  2. CSS Class 选择器

    CSS Class 选择器 再<stype>标签内,通过class属性来对标签进行css样式配置 <html> <head> <!-- style 设置头部标 ...

  3. bzoj1001狼抓兔子 对偶图优化

    bzoj1001狼抓兔子 对偶图优化 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=1001 思路 菜鸡总是要填坑的! 很明显让你求网格图的最 ...

  4. Java三种注释

    单行注释:// 注释内容 多行注释:/*... 注释内容....*/ 文本注释:/**.. 注释内容....*/                     这种注释可以用来自动地生成文档.在JDK中有个 ...

  5. Bellman-Ford算法模板题

    POJ 3259 虫洞(Bellman-Ford判断有无负环的问题) 描述: 在探索他的许多农场时,Farmer John发现了许多令人惊叹的虫洞.虫洞是非常奇特的,因为它是一条单向路径,在您进入虫洞 ...

  6. Angular4.0 项目报错:Unexpected value xxxComponent' declared by the module 'xxxxModule'. Please add a @Pipe...

    最近刚刚开始学习angular 4.0,在网上找了一个小项目教程学习,然而学习的过程有点艰辛,,各种报错,我明明就是按照博主的步骤老老实实走的呀!!话不多说,上bug-  .- Uncaught Er ...

  7. JQUERY的属性进行操作

    Jquery方式操作属性(attribute) $().attr(属性名称);   //获得属性信息值 $().attr(属性名称,值);    //设置属性的信息 $().removeAttr(属性 ...

  8. android -------- 压缩图片文件工具类

    项目中常常遇到文件压缩问题,上传文件大小限制 今天简单的分享一点干货,文件压缩,图片压缩,压缩Bitmap 主要通过尺寸压缩和质量压缩,以达到清晰度最优 效果图 源码地址: https://githu ...

  9. php 搜索附近人及SQL语句的写法

    /** * 根据经纬度和半径查询在此范围内的所有 * @param String $lat 纬度 * @param String $lng 经度 * @param float $radius 半径 * ...

  10. Oracle的sql导入

    sqlldr: 一般用于导入以任何后缀结束的文件,我这次就是因为要导入一张以.20160101为后缀的文件,当初简直束手无策 结合input.ctl使用,可以在DOS下使用,可以对一张表导入数十万,百 ...