spring源码系列(十): 读取xml入口类 ClassPathXmlApplicationContext 分析
环境准备:
使用spring5.1.6版本

1 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.hou.spring.bean.User"></bean>
</beans>
2 测试类
public class BeanTest{
@Test
public void beanTest(){
//spring4之后XmlBeanFactory被废弃,改用以下方式
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
User user = (User) applicationContext.getBean("user");
System.out.println(user);
}
}
然后点进去源码,跟着一步步debug来分析:
1 构造器调用:
ClassPathXmlApplicationContext的构造器中调用类同名方法:

点击this跳转到初始化方法:

2 super()方法是一直到父类AbstractApplicationContext中,将ApplicationContext的环境属性设置给本类的环境属性,包括一些profile,系统属性等

3 setConfigLocations方法也是调用父类方法,将xml配置文件名字设置给父类的String数组属性

4 refresh() 方法,所有的逻辑其实都在这个方法里面进行,主要分析这个方法:

5 prepareRefresh主要还是环境属性的一些初始化,主要看第二步:
// Tell the subclass to refresh the internal bean factory. 告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
点进去obtainFreshBeanFactory:

6 首先看refreshBeanFactory方法,注意,如果不知道是哪个子类的话,可以跟着debug断点走:

主要分为这么几个步骤:
一 首先判断本类的DefaultListableBeanFactory属性是否为null,如果不为null,就先清除一写跟Bean有关的Map或者List等属性集合
二 将BeanFactory设置为null,序列化id设置为null,
三 创建DefaultListableBeanFactory,这个类很重要,是springBean初始化的核心类,
四 对beanFactory进行设置,bean注册等操作,最后将beanFactory赋值给本类的beanFactory属性
7 customizeBeanFactory(beanFactory); 只做了两件事:

8 loadBeanDefinitions: Bean的注册主要是在这一步进行,下面进行分析,这个方法有5个子类实现:

我写的测试类不是Web项目,所以会进入AbstractXmlApplicationContext这个类里的方法,如果是Web项目,会走XmlWebApplicationContext:

首先创建XmlBeanDefinitionReader:xml配置读写器然后设置环境属性以及资源加载器为ClassPathXmlApplicationContext,这个加载器很重要,后面会用到
接着初始化读取器: initBeanDefinitionReader,最后加载Bean
8 initBeanDefinitionReader
这个方法默认实现是空的,允许用户自定义实现读取器的定制化,需要实现接口,可以设置xml解析完成校验,定制化解析器等
9 loadBeanDefinitions: 加载Bean信息,点进去:

这个方法主要是加载类的两个资源属性,Resource[] 和xml位置信息,主要看加载Xml的:
10 reader.loadBeanDefinitions(configLocations);

循环加载xml文件的Bean返回Bean总个数,查看加载方法:
11 查看这个load方法:

这里需要注意第八步设置的加载器,查看加载器的时序图:

因为有继承关系所以直接进if分支,继续分析if分支代码:

主要步骤:
1 获取加载器中的Resource[] 数组
2 加载资源中的Bean,返回加载数量
12 查看loadBeanDefinitions,循环加载了所有的资源,返回总数

13 查看单个加载方法loadBeanDefinitions,主要看中间一段逻辑:

这里对正在解析的xml资源放入ThreadLocal中,保证只有本次线程可以访问,加载完之后再移除
13 查看doLoadBeanDefinitions(inputSource, encodedResource.getResource());

spring源码系列(十): 读取xml入口类 ClassPathXmlApplicationContext 分析的更多相关文章
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- Ioc容器BeanPostProcessor-Spring 源码系列(3)
Ioc容器BeanPostProcessor-Spring 源码系列(3) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Io ...
- Ioc容器beanDefinition-Spring 源码系列(1)
Ioc容器beanDefinition-Spring 源码系列(1) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器 ...
- AOP执行增强-Spring 源码系列(5)
AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...
- Spring源码系列 — 注解原理
前言 前文中主要介绍了Spring中处理BeanDefinition的扩展点,其中着重介绍BeanDefinitionParser方式的扩展.本篇文章承接该内容,详解Spring中如何利用BeanDe ...
- Spring源码系列 — BeanDefinition扩展点
前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition ...
- Spring源码系列 — BeanDefinition
一.前言 回顾 在Spring源码系列第二篇中介绍了Environment组件,后续又介绍Spring中Resource的抽象,但是对于上下文的启动过程详解并未继续.经过一个星期的准备,梳理了Spri ...
- 事件机制-Spring 源码系列(4)
事件机制-Spring 源码系列(4) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcess ...
- Ioc容器依赖注入-Spring 源码系列(2)
Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...
随机推荐
- Docker 说明
一.Docker 是什么? 1.为什么会有 Docker 出现 ? 一款产品从开发到上线,从操作系统,到运行环境,再到应用配置.作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得 ...
- spring定时器时间设置规则
单纯针对时间的设置规则org.springframework.scheduling.quartz.CronTriggerBean允许你更精确地控制任务的运行时间,只需要设置其cronExpressio ...
- 百度DMA+小度App的蓝牙语音解决方案技术难点解析
前记 你平时在商场看到的语音助手,看起来非常的简单,其实,这个小小语音助手的背后,是一个非常的复杂的技术支撑.从前端到后端的技术依次是:前端语音降噪技术,高效的音频编解码技术,蓝牙双模技术,DMA ...
- [梁山好汉说IT] 梁山好汉和秒杀系统
[梁山好汉说IT] 梁山好汉和秒杀系统 0x00 摘要 今天看了一篇好文章,里面一些思路颇值得借鉴.先摘录总结精华.然后看看梁山好汉如何处理秒杀系统(系统隔离/系统搭建/风控过滤/削峰/信号广播... ...
- 【一起学源码-微服务】Nexflix Eureka 源码十一:EurekaServer自我保护机制竟然有这么多Bug?
前言 前情回顾 上一讲主要讲了服务下线,已经注册中心自动感知宕机的服务. 其实上一讲已经包含了很多EurekaServer自我保护的代码,其中还发现了1.7.x(1.9.x)包含的一些bug,但这些问 ...
- beta 1/2 阶段中间产物提交入口
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/9918 git地址:https://e.coding.net/Eustia ...
- 1028 人口普查 (20 分)C语言
题目描述 某城镇进行人口普查,得到了全体居民的生日.现请你写个程序,找出镇上最年长和最年轻的人. 这里确保每个输入的日期都是合法的,但不一定是合理的--假设已知镇上没有超过200岁的老人,而今天是20 ...
- linux条件变量使用和与信号量的区别
近来在项目中用到条件变量和信号量做同步时,这一块一直都有了解,但也一直没有总结,这次总结一下,给大家提供点参考,也给自己留点纪念. 首先,关于信号量和条件变量的概念可以自行查看APUE,我这直接把AP ...
- 11.在Chrome谷歌浏览器中安装插件XPath Helper的方法
1.首先在以下链接下载XPath Helper插件,链接:https://pan.baidu.com/s/1Ng7HAGgsVfOyqy6dn094Jg 提取码:a1dv 2.插件下载完成后解压,然后 ...
- 深入浅出 Typescript 学习笔记
TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准. TypeScript 由微软开发的自由和开源的编程语言. TypeScript 设计目标是开发大型应 ...