手绘SpringIOC时序图
通过绘制序图来一步步了解springIOC初始化的原理
总体来说,springIOC初始化可以分为三个模块------定位、加载和注册
再细分下去17个小模块
1.寻找入口——>2.获取配置文件路径——>3.容器开始启动——>4.开始解析配置文件路径——>5.载入配置路径——>6.分配路径处理策略——>7.解析配置文件路径——>8.加载配置文件信息——>9.开始解析配置文件——>10.分配解析配置文件策略——>11.将配置文件载入到内存——>12.载入<bean>元素——>13.载入<property>元素——>14.载入<property>子元素——>15.载入<list>子元素——>16.分配注册策略——>17.开始向容器注册
图片中1-14可划归到定位,15-24加载,25-26注册
下面我将逐个步骤加以介绍
可能会有小伙伴有疑问,我在看源码的过程中是怎么找到这个切入点的呢?其实很简单,我是从应用反向推导出切入点,
回想当初我们在调用Spring的容器进行bean的获取时,一般在主程序中这么写:
//创建Spring的工厂
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
我们都知道ApplicationContext是BeanFactory的一个子接口,算是SpirngIOC的一个容器,也叫Spring上下文。这就使我把目标投向了ClaasPathXmlAppliccation这个类。点开看一下
可以看出来ClassPthXmlApplicationContext的构造函数做了三件事(只有一个参数的构造函数最终也会调到这个方法上来)。
一.super(parent)
这调用了父类的构造函数,接下来的流程对应时序图中的1-8,主要是为了完成对配置文件路径的解析
我们按着时序图一路super点下去最终到了AbstractApplicationContext这个类,即第5步。
发现这里调了个this()的本类的构造函数和setParent这个方法。在构造函数里又调用了getResourcePatternResolver();
从名字上看应该能推测是做资源解析处理的,并赋值给成员变量resourcePatternResolver。
点进这个成员变量
发现这是一个接口继承ReourceLoader并且有getResources方法。看到这里我们明白了,原来getResourcePatternResolver是
返回一个资源加载器来方便我们后续去读取配置文件。其实看到这里按理说对这个方法也没必要点进去深入了解了。但是好奇心使我还是想一探究竟,点进getResourcePatternResolver方法看看它是如何返回这个资源加载器的
可以看到PthMatchingResourcePatternResolver是要求传入一个ResourceLoader类型的并且还赋值到了自己的成员变量上。但是为什么我们在上面new的时候只传入了一个this呢?原因就是这个类是ResourceLoader的一个实现的子类,所以不冲突。
回到上面AbstractApplicationContext的setParent方法,其实就是给父容器赋值,但实际上我们在代码中初始化的时候只传入了一个String路径名的话,这个值是赋空的。
二:setConfigLocations(configLocations)
这个就是讲路径字符串解析并且赋值到容器中的一个资格字符串数组中,感兴趣的朋友可以深入讨论,这里不再赘述。
三:refresh()
refresh()方法的主要作用是:在创建 IOC 容器前,如果已经有容器存在,则需要把已有的容器销毁和
关闭,以保证在 refresh 之后使用的是新建立起来的 IOC 容器。它类似于对 IOC 容器的重启,在新建立
好的容器中对容器进行初始化,对 Bean 配置资源进行载入
图截多了一部分,原谅博主还不太会用长截屏。
总之从图片上可以看到这是一个模板方法模式,这里规范了容器加载注册的标准流程。其中真正干主活obtainFreshBeanFactory告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 子类的refreshBeanFactory()方法启动。顺着时序图找到doLoadBeanDefinitions方法,找到这个就很激动,因为spring中真正做事的都是以do开头的,其他同名不带do的都是负责统筹调度的。
其实这段代码只做了三件事,这三件事的每一件都必不可少
(1)获取对XML文件的验证模式
(2)加载XML文件,并得到对应的Document
(3)根据返回的 Document注册Bean信息
这个三个步骤支撑着整个Spring容器部分的实现,尤其是第三步对配置文件的解析
这就完成了对配置文件的定位和加载和注册