大家好,用零碎的时间陪大家一起撸源码,让源码不再成为你升职加薪路上的绊脚石!
我们接着上一篇《深入了解Spring源码细节(1) -getEnvironment是怎么获取到值的?》继续往下讲,如果没有看过上一篇的建议看一下上一篇内容,不然你可能会懵逼!
公众号:读书人王元存
上一章我们把prepareRefresh()这个方法讲完了,今天重点来讲一下这个:
ConfigurableListableBeanFactory beanFactory =
obtainFreshBeanFactory();
这个方法非常重要,它主要的作用其实就是创建容器对象DefaultListableBeanFactory 以及把配置文件中xml等信息加载到BeanDefinition.
看过我写的第一篇文章《搞清spring源码的脉络,你就知道从哪里开始下手了》:
公众号:读书人王元存
不知道你还记不记这篇文章里面最重要的一张图片如下:
大家看这张图的时候有没思考过这样一个问题,他们的执行顺序是怎么样的?
好吧,不管你知道还是不知道,继续往下看,看是否最终源码内的答案是否和你想的一致!
首先我们点开refreshBeanFactory()这个方法如下:
老规矩我们还是先看注释,通过注释大概知道这个方法是干嘛的,注释如下:
This implementation performs an actual refresh of this context's underlying bean factory, shutting down the previous bean factory (if any) and initializing a fresh bean factory for the next phase of the context's lifecycle.
这个注释大致可以翻译成两部分(如果不正确欢迎大家指证哈):
1:shutting down the previous bean factory (if any) --关闭之前已经存在的工厂;
2:initializing a fresh bean factory for the next phase of the context's lifecycle。--为下个阶段的上下文生命周期初始化一个新的bean工厂;
这一步就是判断是否已经存在beanFactory,如果已经存在的话则销毁beanFactory.
DefaultListableBeanFactory beanFactory =
createBeanFactory(); 这行代码看这个方法名字我们就算不看里面具体的内容也大概能猜出来他是干嘛的,就是创建一个beanFactory的实现类DefaultListableBeanFactory.这个方法希望大家可以记住,后面会经常看到这个类,这也也佐证了下面的图的第1步:创建容器;
现在我们继续往下走,看代码里面的实现是否如我们上图所圈出来第2步和第3步那样处理的。
上面我圈出来的这个地方大家可以点进去看看,这个方法主要其实就是设置beanFactory里面的两个属性:
1:allowBeanDefinitionOverriding:是否允许覆盖同名称的不同定义的对象;
2:allowCircularReferences:是否允许自动去解决bean之间存在的循环依赖问题;
这个方法你开始debug进来的时候其实这两个if条件都是进不去的,如果你想改变这两个字段的值的话,可以通过子类来实现,代码如下:
如果大家想要这个源码的话,可以私聊我源码地址,一起学习!
我们继续往下走,接下来就是我们本篇最核心的方法了:
我们点开这个方法如下:
上面标注的1这个不用说了,这个就是创建一个XmlBeanDefinitionReader,这个方法主要是为了解析xml里面bean的信息,以便于转换成BeanDefinition信息。
这个接口我们就不展开讲了,后面有时间再详细的出一篇详细的讲一下,大家先知道它是干嘛的就OK了。
这个标注的2里面的内容this.getEnvironment()所对应的值其实就是上一章《深入了解Spring源码细节(1) -getEnvironment是怎么获取到值的?》所写的内容,大家可以看看
公众号:读书人王元存
这也验证了我们前面的脉络图里面的步骤:
我们继续往下看这个步骤3,是不是和我们画的这个一致,我们点开
loadBeanDefinitions(beanDefinitionReader)如下:
这个方法的作用其实在它的注释里面已经写的非常清楚了:
Load the bean definitions with the given XmlBeanDefinitionReader
通过xmBeanDefinitionReader来加载bean的definitions信息;
this method is just supposed to load and/or register bean definitions
这个方法只是支持加载bean definitions的注册;
我们直接进入reader.loadBeanDefinitions(configLocations)如下:
我们再直接进入loadBeanDefinitions(location),然后再一步步往下走(中间省略一些步骤)一步步往下走会得到下面的图:
doLoadBeanDefinitions(inputSource,encodedResource.getResource())
这个方法是核心方法,其实在源码中,只要你看到了do相关的方法都是真正干活的方法。
上面图片中第1步大概的意思就是把xml里面的信息转换成一个document文档,为后面转化成BeanDefinition的对象做准备;
上面图片中第2步就是核心的把document文档内容转换成BeanDefinition信息;
这个我们今天就不说了,下篇我们讲这个document到BeanDefinition的转换;
关注我,一起读书,一起提升认知!