干货分享之Spring框架源码解析01-(xml配置解析)
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新。欢迎大家指正!
环境: spring5.X + idea
Spring 是一个工厂,是一个负责对象的创建和维护的工厂。它给我提供了一个功能齐全而且方便我们使用的ApplicationContext子接口,它最底层的接口是BeanFactory。在这个BeanFactory下面衍生了各种功能的子接口。
- 容器管理HierarchicalBeanFatory
- 自动注入AutowireCapableBeanFactory
- 读取配置信息ListableBeanFactory
可以自行找一下BeanFactory类关系图,它有一个子实现类XmlBeanFactory,先说一下XML配置文件的读取
ListableBeanFactory 是读取配置信息的,它的子实现类XmlBeanFactory就是读取xml文件的具体实现。
而ApplicationContext继承了ListableBeanFactory并对xml解析做了进一步的封装所以再我们使用ApplicationContext
时直接给他一个对应位置的资源文件名它就会帮我们读取到配置信息。
ApplicationContext ctx = new ClassPathXmlApplicatiionContext("applicationContext.xml");
User user = ctx.getBean("user");
//我们直接用最底层的接口 BeanFactory 获取xml信息
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
User user = bf.getBean("user");
说明:
- beanFactory 底层获取xml文件信息的实现类 XmlBeanFactory 需要传入一个 ClassPathResource 对象。这个对象的父接口就是InputStreamSource 他就是提供了一个获取输入流的方法
InputStream getInputStream() throws IOException;
而ClassPathResource 对这个方法的实现就是通过类或者类加载器实现的
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
}
else if (this.classLoader != null) {
is = this.classLoader.getResourceAsStream(this.path);
}
获取了输入流那就自然可以获取文件的内容了。
- Spring获取xml内容后通过XmlBeanDefinitionReader解析配置文件的内容封装成BeanDefinition方便后续使用。
//前边说了是XmlBeanFactory具体实现获取xml信息的功能
1. public class XmlBeanFactory extends DefaultListableBeanFactory {
//xmlBeanFactory 中直接实例化 xmlBeanDefinitionReader
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
.....
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
}
2. public class XmlBeandefinitionReader extends AbstractBeanDefinitionReader{
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
......
try (
//获取输入流
InputStream inputStream = encodedResource.getResource().getInputStream()) {
//xml 解析工具类
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
//开始具体解析
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
......
}; protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// xml 解析为 document
Document doc = doLoadDocument(inputSource, resource);
// document 转 beanDefinition
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
}
}
3. public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
protected void doRegisterBeanDefinitions(Element root){
...
preProcessXml(root);
parseBeanDefinitions(root,this,dalegate);
postProcessXml(root);
}; protected void parseBeanDefinitions(Element root,BeanDefinitionParseDelegate delegate){
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//解析基本标签
parseDefaultElement(ele, delegate);
}
else {
//解析自定义标签
delegate.parseCustomElement(ele);
}
}
}
}
} }
解释说明:
通过 XmlBeanDefinitionReader 的 loadBeanDefinitions 方法得到输入流和xml解析工具类在 doLoadBeanDefinitions方法中把输入流也就是获得的xml文件信息转化为 Document 再通过 registerBeanDefinitions 方法封装成 beanDefinition封装beanDefinition是在 DefaultBeanDefinitionDocumentReader 类中的doRegisterBeanDefinitions . parseBeanDefinitions方法做了具体功能的实现,也就是解析文件中的标签并和beanDefinition的属性做映射。例如: 根标签(beans、prefile等) 子标签 (基本标签 bean、import、alias等,自定义标签 aop、mvc:annotation-driven、tx:annotation-driven、context:等)用 BeanDefinitionParserDelegate 把解析标签得到的值映射成beanDefinition方便后续使用。
最后
感谢您的阅读,有什么意见和问题欢迎评论区留言!书写不易!
觉得文章对你有帮助记得给我点个赞,欢迎大家关注和转发文章!
干货分享之Spring框架源码解析01-(xml配置解析)的更多相关文章
- 干货分享之spring框架源码分析02-(对象创建or生命周期)
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 之前分析了Spring读取xml文件的所有信息封装成beanDef ...
- Spring AMQP 源码分析 08 - XML 配置
### 准备 ## 目标 通过 XML 配置文件使用 Spring AMQP ## 前置知识 <Spring AMQP 源码分析 07 - MessageListenerAdapter> ...
- Spring源码-IOC部分-Xml Bean解析注册过程【3】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- Spring框架源码干货分享之三级缓存和父子工厂
记录并分享一下本人学习spring源码的过程,有什么问题或者补充会持续更新.欢迎大家指正! 环境: spring5.X + idea 建议:学习过程中要开着源码一步一步过 Spring中对象的创建宏观 ...
- Spring框架源码阅读之Springs-beans(一)容器的基本实现概述(待续)
去年通过实际框架代码的阅读,以及结合<Spring源码深度解析>和<Spring技术内幕>的阅读,对Spring框架内Bean模块有了一个整体性的认识.对此进行的总结性整理和回 ...
- spring beans源码解读之--bean definiton解析器
spring提供了有两种方式的bean definition解析器:PropertiesBeanDefinitionReader和XmLBeanDefinitionReader即属性文件格式的bean ...
- Spring MVC源码(四) ----- 统一异常处理原理解析
SpringMVC除了对请求URL的路由处理特别方便外,还支持对异常的统一处理机制,可以对业务操作时抛出的异常,unchecked异常以及状态码的异常进行统一处理.SpringMVC既提供简单的配置类 ...
- 设计模式(五)——原型模式(加Spring框架源码分析)
原型模式 1 克隆羊问题 现在有一只羊 tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和 tom 羊 属性完全相同的 10 只羊. 2 传统方式解决克隆羊问题 1) 思路分析(图 ...
- spring框架源码编译
程序猿小菜一枚,最近从github上面下载下来一份spring各个项目的源码一份,但是弄了很长时间,因为网速和(fanqiang)的速度,希望大家不要再为这种无谓的时间花费时间,简单来说github上 ...
随机推荐
- openCV入门系列教学(一) 图像的读取、展示与保存
序言 笔者最近做了两个CV领域的项目,因为数据量不足所以主要使用的是传统的CV方法.这时候不得不夸一句opencv库,让复杂的算法原理变得如此简单(调包调参侠表示很骄傲).所以闲暇下来对opencv的 ...
- 不用调整Nginx,SpringBoot也能解决前端访问的跨域问题
1.什么情况下会出现跨域问题 通常,在前端工程师的开发过程中,往往在本地机器启动前端服务, 而调用的后端接口服务是在另外一台机器运行,这时就会出现跨域问题,让接口无法调通. 而到了测试环境和生产环境, ...
- netty系列之:轻轻松松搭个支持中文的服务器
目录 简介 netty的HTTP支持 netty中使用HTTP的原理 100 (Continue) Status 为netty搭建HTTP服务器 总结 简介 之前讲了那么多关于netty的文章,都是讲 ...
- mongodb重启报错解决
mongodb关闭后重启失败 connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName= ...
- 高德地图——公交路线规划(关键字&坐标)
&plugin=AMap.Transfer 1.关键词方式---不支持途径(仅支持2个数据) <!DOCTYPE html> <html> <head> & ...
- 恶意软件开发——shellcode执行的几种常见方式
一.什么是shellcode? shellcode是一小段代码,用于利用软件漏洞作为有效载荷.它之所以被称为"shellcode",是因为它通常启动一个命令shell,攻击者可以从 ...
- 由Eratosthenes筛法演变出的一种素数新筛法
这两天和walls老师交流讨论了一个中学竞赛题,我把原题稍作增强和变形,得到如下一个题: 从105到204这100个数中至少要选取多少个数才能保证选出的数中必有两个不是互素的? 我们知道最小的几个素数 ...
- centos7 权限更改,所属用户及用户组更改
2021-08-03 # 查看文件的权限 ll 第一个字符, "-" 表示是文件, "d" 表示是目录(directory) 后面 9 个字符每 3 个字符又作 ...
- golang redis
安装 下载第三方包: go get -u github.com/go-redis/redis/v9 连接 // 定义一个rdis客户端 var redisdb *redis.Client // 初始化 ...
- Week2 题解
T1及题解 T2 CF1207E 首先,异或这个位运算有个很好的性质:x^y^y=x 于是,可以有两种解决方法: 法一 既然让猜原来的数是多少,当它异或了一个其他值val的时候,再异或val就会变回原 ...