Spring WebApplicationContext 准备刷新过程

Spring 框架WebApplicationContext 准备刷新的过程做了什么事情 ?

之前粗略的看了下Spring web这块初始化的过程,当时的重心是放在了容器的初始化过程,如果解析配置文件,以及如何初始化FactoryBean, 今天则是把重心放在了初始化过程中的一些小细节上。 下面看看问题的引出:

Spring WebApplicationContext 准备刷新过程_第1张图片


图为WebApplicationContext刷新的整个过程,但是今天主要是想弄明白的是prepareRefresh()这个“准备刷新”方法干了什么事情。

1. 打开这个方法看看究竟:

Spring WebApplicationContext 准备刷新过程_第2张图片


可以注意到,就干了两个事情,先是初始化propertySources 然后验证必要的properties,

2.接下来我们看看initPropertySources()它的实现。



3.知道这个类是哪一个类么,如果不知道,先不管,点进去看看



这一看就明白了,首先调用父类的initPropertySources()方法,然后再获取当前环境初始化自己的property。

4.那么问题又来了,这个环境是个什么东西,我们不妨打开看看

Spring WebApplicationContext 准备刷新过程_第3张图片


这里调用了父类的创建环境的方法,但是还是不知道这个环境是什么东西,继续点。再点就来到了AbstractApplicationContext这个类



这仅仅是返回一个引用,那么这个环境在哪里创建的? 那就继续点这个变量呗。通过一点,一搜,在这个类中发现了产生它的地方:

Spring WebApplicationContext 准备刷新过程_第4张图片


这不在构造器中么? 对,这说明只要我们初始化AbstractApplicationContext就会创建环境,来看看这个环境是什么,

Spring WebApplicationContext 准备刷新过程_第5张图片


反正就是一个类,就不用管它了,反正知道是这个东西就行了。 但是问题来了,AbstractApplicationContext是一个抽象类,初始化话工作由谁来完成的呢 ?这个时候我们不得不考虑一个问题,就是createEnvironment()这个创建环境的方法有没有被子类重写呢,

5.我们点开看看。



Eclipse显示是有被重写了的,

6.那就点进去看看到底是什么

Spring WebApplicationContext 准备刷新过程_第6张图片


我艹,看到这里似乎应该明白了,原来创建的环境是标准servlet环境。 现在环境创建好了,我们刚才的问题还没有解决呢,就是初始化property,忘记了?在第3步那里,获取了环境,然后调用了initPropertySources()方法,如下,



7.接下来就可以看看这个方法干了什么事情了,进入到StandardServletEnvironment这个类,看看究竟



这是个鸟东西? 不知道,继续点,



这里在对这个property容器做判断,看看里面是否包含一个key,如果包含干一些事情,那么这个时候又纳闷了,这个property这一路走来都没有初始化它的地方啊,在哪里初始化的呢 ? 不要慌,这个是参数传进来的,我们倒回去一步看看, 原来是通过this.getPropertySources()获取到的,再进去看看,突然就来到了AbstractEnvironment这个类



光是这样一句话是看不出来哪里初始化的,那么我们搜一搜在这个类中,结果在构造方法中发现了它的踪影,

Spring WebApplicationContext 准备刷新过程_第7张图片


看看这个方法:



空的,很明显是子类重写的这个方法,那就点看看呗。

Spring WebApplicationContext 准备刷新过程_第8张图片


恍然大悟,尼玛原来就在我们来的路上已经错误了它,赶紧看看先,

Spring WebApplicationContext 准备刷新过程_第9张图片


这里不就对它放值了么,它下面一个方法没忘记吧? 初始化property,当时就是从它开始找这个property容器是在哪里初始化的,这下明白了。

8.那么看看准备过程中的最后一个问题,验证property:

Spring WebApplicationContext 准备刷新过程_第10张图片


现在其实逻辑都会很清晰了,因为我们知道这里的环境是哪一个,我们直接点进去看看这个验证到底干了什么事情:

Spring WebApplicationContext 准备刷新过程_第11张图片


很明显,这里说的是,如果这个必要的property容器中存在值为空的那种情况,则抛出异常,这样就验证完成了。
到这里整个“准备刷新”的过程就完成了,这个过程还是有点绕,因为调用了很多子类重写的方法。 这里再理一理整个过程,首先AbstractApplicationContext初始化过程会调用createEnvironment()方法创建环境,这个方法被子类重写,最终创建的是StandardServletEnvironment.  这个环境的创建过程会调用customizePropertySources()方法配置当前这个环境需要的property, 然后在初始化property的过程时,会调用当前环境,然后调用initPropertySources(),这个方法会根据现在property容器里面的值,封装一些property类进去。最后验证的这个东西太简单,就不说了。

最后附上一张类关系图,这样看上去思路就比较清晰了:



你可能感兴趣的:(spring,框架)