Spring源码学习(3)—— 自定义标签
上一篇讲了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)—— 自定义标签的更多相关文章
- Spring 源码学习(1) —— 自定义标签
Spring 工作流程是先加载解析xml配置文件:配置文件中存在默认的标签,也可以自定义标签.解析默认标签调用: private void parseDefaultElement(Element el ...
- spring源码学习之默认标签的解析(一)
继续spring源码的学习之路,现在越来越觉得这个真的很枯燥的,而且我觉得要是自己来看源码,真的看不下去,不是没有耐心,而是真的没有头绪,我觉得结合着书来看,还是很有必要的,最起码大致的流程是能够捋清 ...
- spring源码学习之默认标签的解析(二)
这个是接着上一篇来写,主要是这章内容比较多,还是分开来写吧! 一.AbstractBeanDefinition属性介绍 XML中的所有的属性都可以在GenericBeanDefinition中找到对应 ...
- spring源码研究2 自定义标签实现及使用
1.自定义标签实现及使用参考: http://blog.csdn.net/fighterandknight/article/details/50112701 1)创建一个需要扩展的组件 User.ja ...
- Spring源码学习-容器BeanFactory(四) BeanDefinition的创建-自定义标签的解析.md
写在前面 上文Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签对Spring默认标签的解析做了详解,在xml元素的解析中,Spri ...
- Spring源码学习-容器BeanFactory(三) BeanDefinition的创建-解析Spring的默认标签
写在前面 上文Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作中Spring对XML解析后创建了对应的Docum ...
- Spring源码学习
Spring源码学习--ClassPathXmlApplicationContext(一) spring源码学习--FileSystemXmlApplicationContext(二) spring源 ...
- Spring源码学习-容器BeanFactory(二) BeanDefinition的创建-解析前BeanDefinition的前置操作
写在前面 上文 Spring源码学习-容器BeanFactory(一) BeanDefinition的创建-解析资源文件主要讲Spring容器创建时通过XmlBeanDefinitionReader读 ...
- Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点
Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...
- spring源码学习之路---IOC初探(二)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 上一章当中我没有提及具体的搭 ...
随机推荐
- Java 多重catch语句的具体使用介绍
某些情况,由单个代码段可能引起多个异常.处理这种情况,你可以定义两个或更多的catch子句,每个子句捕获一种类型的异常.当异常被引发时,每一个catch子句被依次检查,第一个匹配异常类型的子句执行.当 ...
- Eclipse中XML文件自定义格式化配置
1,编码格式:UTF-8 2,Line Width:90,Indent using spaces:2 3,默认编辑器 当添加Spket插件后,xml文件默认编辑器将被修改为Spket,要求恢复默认,则 ...
- 使用solr进行配置文件
我现在使用的是一个已经搭建好的solr环境下进行的测试: 第一步,需要配置solrhome中的一个配置文件schema.xml 配置内容如下,上面配置的是IK分词器,下面是配置完成的域. 因为我在这个 ...
- python爬虫——与不断变化的页面死磕和更新换代(3)
经过上一次的实战,手感有了,普罗西(雾)池也有了,再战taobao/tmall 试着使用phantomJS爬手机端,结果发现爬来的tmall页面全是乱码,taobao页面xpath识别错误.一顿分析了 ...
- pytesseract使用的坑
今天学了下python的OCR识别,其中遇到好多坑,下面就一一阐述是如何破解的,本人用的是Windows 64位,IDE是VS2017. pip版本过低. 首先安装pytesseract这个库,pip ...
- Docker Swarm 创建服务
Docker Swarm 创建服务 环境: 系统:Centos 7.4 x64 应用版本:Docker 18.09.0 管理节点:192.168.1.79 工作节点:192.168.1.78 工作节点 ...
- 【双目备课】OpenCV例程_stereo_calib.cpp解析
stereo_calib是OpenCV官方代码中提供的最正统的双目demo,无论数据集还是代码都有很好实现. 一.代码效果: 相关的内容包括28张图片,1个xml和stereo_calib.cpp的代 ...
- 剑指offer(51)构建乘积数组
题目描述 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1].不 ...
- 剑指offer(57)二叉树的下一个节点
题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 题目分析 这题一定要画图,因为只有画图我们才能分清楚下 ...
- web前端除了关注代码功能实现,还应具备web性能优化以及SEO优化的常识
web前端除了关注代码功能实现,还应具备web性能优化以及SEO优化的常识 ——不会WPO.SEO的前端工程师不是好码农 作为一名web前端工程师,除了要实现上级的要求,满足其所需要的功能,还要在平时 ...