最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

21-Spring高級容器初始化:初始化非延遲加載單例bean

2023-06-18 18:53 作者:儒猿課堂  | 我要投稿

開篇


上一節(jié),我們了解了在Spring中是如何基于事件驅(qū)動開發(fā)的,其實就是將監(jiān)聽器注冊到事件廣播器中,然后當Spring發(fā)布事件時,事件廣播器會遍歷所有注冊的監(jiān)聽器,并通過監(jiān)聽該事件的監(jiān)聽器來處理事件。


這一節(jié),我們主要來了解下一下ApplicationContext初始化過程中最后的一些邏輯,主要包括以下幾個部分:

1.看下ApplicationContext是如何注冊監(jiān)聽器的

2.看下ApplicationContext是如何初始化非延遲加載單例的

3.最后來看下ApplicationContext是如何開啟Spring的生命周期的


注冊監(jiān)聽器ApplicationListener


接下來,我們繼續(xù)回到refresh方法中來:

可以看到,在前面的方法initApplicationEventMulticaster分析完之后,我們接著再到方法onRefresh中看下:

可以看到方法onRefresh也是一個空實現(xiàn)方法,和之前很多的空實現(xiàn)方法一樣,方法onRefresh也是由關鍵字protected修飾的,也就是說方法onRefresh也是Spring留給子類的一個擴展方法。

我們繼續(xù)往后面看:

可以看到,通過方法registerListeners的名稱,我們大概可以知道應該是要注冊一些監(jiān)聽器了,那具體是如何注冊的呢?可以到方法registerListeners里面看下:

可以看到,在方法registerListeners中也沒有什么特別的東西,比較關鍵的無非也就是將參數(shù)中的監(jiān)聽器以及從Spring容器中獲取到的監(jiān)聽器,分別都注冊到廣播器中。

從這里我們可以知道在上一節(jié)的內(nèi)容中,為什么我們可以從廣播器中獲取到監(jiān)聽器了。


初始化非延遲加載的單例


其實分析到這里,ApplicationContext的初始化環(huán)節(jié)已經(jīng)差不多快結(jié)束了,我們把后面一些收尾的地方來看下,再次回到refresh方法:

跟進到方法finishBeanFactoryInitialization中看下:

可以看到,在finishBeanFactoryInitialization方法中,其實就是初始化了一些比較瑣碎的東西,我們重點來看下beanFactory調(diào)用的方法preInstantiateSingletons:

可以看到,在方法preInstantiateSingletons中,首先會遍歷所有注冊到Spring容器中的BeanDefinition,如果BeanDefinition的屬性scope的值為singleton也就是單例的,同時屬性lazyInit的值為false,說明該BeanDefinition對應的bean是不允許懶加載的單例。


既然bean不允許懶加載,那當然就要立馬去加載它了,所以,我們可以看到接下來就會調(diào)用getBean方法去實例化bean了,又因為bean的屬性scope值為singleton,也就是bean是單例的,所以,Spring會把實例化好的bean放一份到單例緩存中。

這樣的話,當Spring下一次要用到bean的實例時,就可以直接從單例緩存中獲取bean的實例了,默認情況下配置的bean都是不會在Spring容器初始化時加載的。


但是,如果你希望自己配置的bean不要懶加載,而是在Spring容器初始化時就率先去加載它,那你完全可以為這個bean配置屬性lazyInit的值為false,就像這樣:

<bean?id="student"?class="com.ruyuan.container.Student"?lazy-init="false"/>


開啟Spring的生命周期


最后,refresh方法中還剩最后一塊邏輯,我們來看下:

我們跟進到finishRefresh方法中看下:

可以看到finishRefresh方法中其實也就沒有太多東西了,主要初始化和生命周期相關的一些組件,我們可以先到initLifecycleProcessor方法,看下做了哪些事情:

可以看到,在方法initLifecycleProcessor中,首先就是到Spring容器中看下是否存在名稱為lifecycleProcessor的bean。

如果存在的話,直接從Spring容器中獲取出來,并賦值給成員變量lifecycleProcessor,如果不存在的話默認會創(chuàng)建一個DefaultLifecycleProcessor類型的對象,并賦值給成員變量lifecycleProcessor,最后再注入到Spring容器中,那DefaultLifecycleProcessor又是什么呢?


其實DefaultLifecycleProcessor是Spring中,處理Spring生命周期相關的一個組件,Spring提供生命周期的接口Lifecycle,這塊我們可以結(jié)合DefaultLifecycleProcessor的類繼承圖看下:

可以看到,DefaultLifecycleProcessor最終也是實現(xiàn)接口Lifecycle的,而LifecycleProcessor接口也只不過是Lifecycle接口的一個擴展接口而已,我們可以看下這兩個接口中的方法:

在Spring中如果bean實現(xiàn)了接口Lifecycle,Spring會保證在容器啟動時,就會調(diào)用這些bean中的start方法開啟它們的生命周期,當然,在Spring關閉的時候也會調(diào)用stop方法來結(jié)束它們的生命周期。


而LifecycleProcessor在Lifecycle的基礎上,又添加了兩個方法onRefresh和onClose,主要就是對相應的bean做狀態(tài)更新,關于onRefresh方法的邏輯,我們可以來看下:

可以看到,接下來會調(diào)用LifecycleProcessor中的onRefresh方法,我們到onRefresh方法中看下:

可以看到在onRefresh方法中,像我們剛才分析的一樣,就會從Spring容器中獲取所有實現(xiàn)了Lifecycle接口的bean,然后調(diào)用start方法來開啟它們的生命周期,也就是開啟Spring的生命周期了。


最后,方法finishRefresh的一些邏輯我們也來看下:

可以看到,其實就是發(fā)布了一個刷新上下文的事件ContextRefreshedEvent。

根據(jù)我們前面的源碼分析,事件ContextRefreshedEvent將會注冊到廣播器中,廣播器會把該事件廣播器相應的監(jiān)聽器去處理,這個事件相當于告訴Spring整個容器已經(jīng)刷新了,也就說Spring容器ApplicationContext已經(jīng)初始化完畢了。


總結(jié)


這一節(jié),主要有以下幾個重要的點:


通過一張圖來梳理下這兩節(jié)課的內(nèi)容:


上一節(jié),我們看到了ApplicationContext初始化了消息源以及事件廣播器,而且通過一個案例我們對廣播器如何結(jié)合監(jiān)聽器以及事件的使用,也有了一定的認識了。

這一節(jié),我們陸續(xù)又了解了Spring是如何注冊監(jiān)聽器的,同時是如何初始化非延遲加載的單例bean,相當于在Spring容器初始化環(huán)節(jié)就預先加載這些bean了,這樣在使用這些bean的時候,我們可以盡早獲取到這些bean的實例。

當所有東西都初始化好之后,Spring容器也就初始化完成了,這個時候Spring會初始化生命周期組件LifecycleProcessor,并且通過onRefresh方法,對那些實現(xiàn)了Lifecycle接口的bean開啟生命周期,最后并發(fā)布一個事件,通知Spring容器刷新即容器初始化這件事已經(jīng)完成了。

21-Spring高級容器初始化:初始化非延遲加載單例bean的評論 (共 條)

分享到微博請遵守國家法律
宿松县| 玉溪市| 安国市| 合肥市| 莒南县| 东平县| 阿合奇县| 沐川县| 临朐县| 乐亭县| 奉新县| 磐安县| 任丘市| 定远县| 益阳市| 双桥区| 白山市| 亚东县| 宜丰县| 巴林右旗| 邯郸县| 牟定县| 桑植县| 台安县| 梁平县| 上栗县| 那坡县| 湾仔区| 平谷区| 富裕县| 广东省| 新邵县| 乃东县| 子长县| 昌黎县| 公主岭市| 宿迁市| 金山区| 武乡县| 怀仁县| 东光县|