Spring IOC基于XML容器的初始化(上)
Posted 47号Gamer丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IOC基于XML容器的初始化(上)相关的知识,希望对你有一定的参考价值。
IOC 容器的初始化包括 BeanDefinition 的 Resource 定位、加载和注册这三个基本的过程。我们以ApplicationContext 为例讲解,ApplicationContext 系列容器也许是我们最熟悉的,因为 Web 项目中使用的 XmlWebApplicationContext 就属于这个继承体系,还有 ClasspathXmlApplicationContext等,其继承体系如下图所示:
ApplicationContext 允许上下文嵌套,通过保持父上下文可以维持一个上下文体系。对于 Bean 的查找可以在这个上下文体系中发生,首先检查当前上下文,其次是父上下文,逐级向上,这样为不同的 Spring应用提供了一个共享的 Bean 定义环境。
1、寻找入口
还有一个我们用的比较多的 ClassPathXmlApplicationContext,通过 main()方法启动:
ApplicationContext app = new ClassPathXmlApplicationContext("application.xml");
先看其构造函数的调用:
其实际调用的构造函数为:
![](https://image.cha138.com/20210525/dcb74d34c86140f89c8c1ce94c8aeae2.jpg)
还 有 像 AnnotationConfigApplicationContext 、 FileSystemXmlApplicationContext 、XmlWebApplicationContext 等都继承自父容器 AbstractApplicationContext主要用到了装饰器模式和策略模式,最终都是调用 refresh()方法。
2、获得配置路径
通 过 分 析 ClassPathXmlApplicationContext 的 源 代 码 可 以 知 道 , 在 创 建ClassPathXmlApplicationContext 容器时,构造方法做以下两项重要工作:
首先,调用父类容器的构造方法(super(parent)方法)为容器设置好 Bean 资源加载器。然后,再调用父类AbstractRefreshableConfigApplicationContext的setConfigLocations(configLocations)方法设置 Bean 配置信息的定位路径。通 过 追 踪 ClassPathXmlApplicationContext 的 继 承 体 系 , 发 现 其 父 类 的 父 类AbstractApplicationContext 中初始化 IOC 容器所做的主要源码如下:
AbstractApplicationContext 的默认构造方法中有调用 PathMatchingResourcePatternResolver 的构造方法创建 Spring 资源加载器:
在设置容器的资源加载器之后,接下来 ClassPathXmlApplicationContext 执行 setConfigLocations()方法通过调用其父类AbstractRefreshableConfigApplicationContext的方法进行对Bean配置信息的定位,该方法的源码如下:
![](https://image.cha138.com/20210525/3a62ad60d2f841e6b4fecacb4b40642e.jpg)
![](https://image.cha138.com/20210525/f10bd83162a542e6bd96414471073501.jpg)
通过这两个方法的源码我们可以看出,我们既可以使用一个字符串来配置多个 Spring Bean 配置信息,也可以使用字符串数组,即下面两种方式都是可以的:
ClassPathResource res = new ClassPathResource("a.xml,b.xml");
多个资源文件路径之间可以是用” , ; \\t\\n”等分隔。
ClassPathResource res =new ClassPathResource(new String[]{"a.xml","b.xml"});
至此,SpringIOC 容器在初始化时将配置的 Bean 配置信息定位为 Spring 封装的 Resource。
3、开始启动
SpringIOC 容器对 Bean 配置资源的载入是从 refresh()函数开始的,refresh()是一个模板方法,规定了IOC 容 器 的 启 动 流 程 , 有 些 逻 辑 要 交 给 其 子 类 去 实 现 。 它 对 Bean 配 置 资 源 进 行 载 入ClassPathXmlApplicationContext 通过调用其父类 AbstractApplicationContext 的 refresh()函数启动整个 IOC 容器对 Bean 定义的载入过程,现在我们来详细看看 refresh()中的逻辑处理:
![](https://image.cha138.com/20210525/e6ca1aa909734975b09b0ac197bd8fed.jpg)
![](https://image.cha138.com/20210525/e0f4f8899b2646f1ad240e3e5d95d7c9.jpg)
![](https://image.cha138.com/20210525/a7acc960fcfb4a53b87ec2296e213035.jpg)
refresh()方法主要为 IOC 容器 Bean 的生命周期管理提供条件,Spring IOC 容器载入 Bean 配置信息从 其 子 类 容 器 的 refreshBeanFactory() 方 法 启 动 , 所 以 整 个 refresh() 中“Configurable-ListableBean-Factory beanFactory = obtainFreshBeanFactory();”这句以后代码的都是注册容器的信息源和生命周期事件,我们前面说的载入就是从这句代码开始启动。refresh()方法的主要作用是:在创建 IOC 容器前,如果已经有容器存在,则需要把已有的容器销毁和关闭,以保证在 refresh 之后使用的是新建立起来的 IOC 容器。它类似于对 IOC 容器的重启,在新建立好的容器中对容器进行初始化,对 Bean 配置资源进行载入。
4、创建容器
obtainFreshBeanFactory()方法调用子类容器的 refreshBeanFactory()方法,启动容器载入 Bean 配置信息的过程,代码如下:
AbstractApplicationContext 类中只抽象定义了 refreshBeanFactory()方法,容器真正调用的是其子类 AbstractRefreshableApplicationContext 实现的 refreshBeanFactory()方法,方法的源码如下:
![](https://image.cha138.com/20210525/2858a89649c248da91965d2bc233b824.jpg)
在这个方法中,先判断 BeanFactory 是否存在,如果存在则先销毁 beans 并关闭 beanFactory,接着创建 DefaultListableBeanFactory,并调用 loadBeanDefinitions(beanFactory)装载 bean 定义。
5、载入配置路径
AbstractRefreshableApplicationContext 中只定义了抽象的 loadBeanDefinitions 方法,容器真正调用的是其子类 AbstractXmlApplicationContext 对该方法的实现,AbstractXmlApplicationContext的主要源码如下:loadBeanDefinitions() 方 法 同 样 是 抽 象 方 法 , 是 由 其 子 类 实 现 的 , 也 即 在AbstractXmlApplicationContext 中。
![](https://image.cha138.com/20210525/30c187fd11ed4a618a281cf581232ee0.jpg)
以 XmlBean 读取器的其中一种策略 XmlBeanDefinitionReader 为例。XmlBeanDefinitionReader 调用其父类AbstractBeanDefinitionReader的 reader.loadBeanDefinitions()方法读取Bean配置资源。由于我们使用 ClassPathXmlApplicationContext 作为例子分析,因此 getConfigResources 的返回值为 null,因此程序执行 reader.loadBeanDefinitions(configLocations)分支。
以上是关于Spring IOC基于XML容器的初始化(上)的主要内容,如果未能解决你的问题,请参考以下文章
Spring IOC基于XML容器的初始化(下)
Spring讲解二:Spring中的Bean配置1---基于XML文件的方式
初探Spring------Spring IOC:初始化过程---Resource定位
Spring-IOC容器-Bean管理-基于XML方式超详解!
Spring学习笔记IOC容器及Spring配置详解
Spring5——IOC操作Bean管理(基于xml文件)