首頁(yè)技術(shù)文章正文

Spring bean生命周期分為幾個(gè)階段?

更新時(shí)間:2022-08-15 來(lái)源:黑馬程序員 瀏覽量:

IT培訓(xùn)班

bean 的生命周期從調(diào)用 beanFactory 的 getBean 開(kāi)始,到這個(gè) bean 被銷(xiāo)毀,可以總結(jié)為以下七個(gè)階段:

處理名稱(chēng),檢查緩存→處理父子容器→處理 dependsOn→選擇 scope 策略→創(chuàng)建 bean→類(lèi)型轉(zhuǎn)換處理→銷(xiāo)毀 bean

劃分的階段和名稱(chēng)并不重要,重要的是理解整個(gè)過(guò)程中做了哪些事情。

1. 處理名稱(chēng),檢查緩存

這一步會(huì)處理別名,將別名解析為實(shí)際名稱(chēng)。對(duì) FactoryBean 也會(huì)特殊處理,如果以 & 開(kāi)頭表示要獲取 FactoryBean 本身,否則表示要獲取其產(chǎn)品。

里針對(duì)單例對(duì)象會(huì)檢查一級(jí)、二級(jí)、三級(jí)緩存。

singletonFactories 三級(jí)緩存,存放單例工廠對(duì)象。

earlySingletonObjects 二級(jí)緩存,存放單例工廠的產(chǎn)品對(duì)象。

如果發(fā)生循環(huán)依賴(lài),產(chǎn)品是代理;無(wú)循環(huán)依賴(lài),產(chǎn)品是原始對(duì)象。

singletonObjects 一級(jí)緩存,存放單例成品對(duì)象。

2. 處理父子容器

如果當(dāng)前容器根據(jù)名字找不到這個(gè) bean,此時(shí)若父容器存在,則執(zhí)行父容器的 getBean 流程。父子容器的 bean 名稱(chēng)可以重復(fù)。

3. 處理 dependsOn

如果當(dāng)前 bean 有通過(guò) dependsOn 指定了非顯式依賴(lài)的 bean,這一步會(huì)提前創(chuàng)建這些 dependsOn 的 bean,所謂非顯式依賴(lài),就是指兩個(gè) bean 之間不存在直接依賴(lài)關(guān)系,但需要控制它們的創(chuàng)建先后順序。

4. 選擇 scope 策略

對(duì)于 singleton scope,首先到單例池去獲取 bean,如果有則直接返回,沒(méi)有再進(jìn)入創(chuàng)建流程。

對(duì)于 prototype scope,每次都會(huì)進(jìn)入創(chuàng)建流程。

對(duì)于自定義 scope,例如 request,首先到 request 域獲取 bean,如果有則直接返回,沒(méi)有再進(jìn)入創(chuàng)建流程。

5.1 創(chuàng)建 bean - 創(chuàng)建 bean 實(shí)例

| 有自定義 TargetSource 的情況         | 由 AnnotationAwareAspectJAutoProxyCreator 創(chuàng)建代理返回       |
| Supplier 方式創(chuàng)建 bean 實(shí)例          | 為 Spring 5.0 新增功能,方便編程方式創(chuàng)建  bean  實(shí)例         |
| FactoryMethod 方式  創(chuàng)建 bean  實(shí)例  | ① 分成靜態(tài)工廠與實(shí)例工廠;② 工廠方法若有參數(shù),需要對(duì)工廠方法參數(shù)進(jìn)行解析,利用  resolveDependency;③ 如果有多個(gè)工廠方法候選者,還要進(jìn)一步按權(quán)重篩選 |
| AutowiredAnnotationBeanPostProcessor | ① 優(yōu)先選擇帶  @Autowired  注解的構(gòu)造;② 若有唯一的帶參構(gòu)造,也會(huì)入選 |
| mbd.getPreferredConstructors         | 選擇所有公共構(gòu)造,這些構(gòu)造之間按權(quán)重篩選                     |
| 采用默認(rèn)構(gòu)造                         | 如果上面的后處理器和 BeanDefiniation 都沒(méi)找到構(gòu)造,采用默認(rèn)構(gòu)造,即使是私有的 |

5.2 創(chuàng)建 bean - 依賴(lài)注入
| ------------------------------------ | 
------------------------------------------------------------ |
| 有自定義 
TargetSource 的情況         | 由 AnnotationAwareAspectJAutoProxyCreator 
創(chuàng)建代理返回       |
| Supplier 方式創(chuàng)建 bean 實(shí)例          | 為 Spring 5.0 
新增功能,方便編程方式創(chuàng)建  bean  實(shí)例         |
| FactoryMethod 方式  創(chuàng)建 bean  實(shí)例  | ① 
分成靜態(tài)工廠與實(shí)例工廠;② 工廠方法若有參數(shù),需要對(duì)工廠方法參數(shù)進(jìn)行解析,利用  resolveDependency;③ 
如果有多個(gè)工廠方法候選者,還要進(jìn)一步按權(quán)重篩選 |
| AutowiredAnnotationBeanPostProcessor | ① 
優(yōu)先選擇帶  @Autowired  注解的構(gòu)造;② 若有唯一的帶參構(gòu)造,也會(huì)入選 |
| 
mbd.getPreferredConstructors         | 
選擇所有公共構(gòu)造,這些構(gòu)造之間按權(quán)重篩選                     |
| 采用默認(rèn)構(gòu)造                         | 
如果上面的后處理器和 BeanDefiniation 都沒(méi)找到構(gòu)造,采用默認(rèn)構(gòu)造,即使是私有的 |
5.3 創(chuàng)建 bean - 初始化
| **要點(diǎn)**              | **總結(jié)**                                                     |
| --------------------- | ------------------------------------------------------------ |
| 內(nèi)置 Aware 接口的裝配 | 包括 BeanNameAware,BeanFactoryAware 等                      |
| 擴(kuò)展 Aware 接口的裝配 | 由 ApplicationContextAwareProcessor 解析,執(zhí)行時(shí)機(jī)在  postProcessBeforeInitialization |
| @PostConstruct        | 由 CommonAnnotationBeanPostProcessor 解析,執(zhí)行時(shí)機(jī)在  postProcessBeforeInitialization |
| InitializingBean      | 通過(guò)接口回調(diào)執(zhí)行初始化                                       |
| initMethod            | 根據(jù) BeanDefinition 得到的初始化方法執(zhí)行初始化,即 `<bean init-method>` 或 @Bean(initMethod) |
| 創(chuàng)建 aop 代理         | 由 AnnotationAwareAspectJAutoProxyCreator 創(chuàng)建,執(zhí)行時(shí)機(jī)在  postProcessAfterInitialization |

5.4 創(chuàng)建 bean - 注冊(cè)可銷(xiāo)毀 bean

在這一步判斷并登記可銷(xiāo)毀 bean

判斷依據(jù)

如果實(shí)現(xiàn)了 DisposableBean 或 AutoCloseable 接口,則為可銷(xiāo)毀 bean

如果自定義了 destroyMethod,則為可銷(xiāo)毀 bean

如果采用 @Bean 沒(méi)有指定 destroyMethod,則采用自動(dòng)推斷方式獲取銷(xiāo)毀方法名(close,shutdown)

如果有 @PreDestroy 標(biāo)注的方法

存儲(chǔ)位置

singleton scope 的可銷(xiāo)毀 bean 會(huì)存儲(chǔ)于 beanFactory 的成員當(dāng)中

自定義 scope 的可銷(xiāo)毀 bean 會(huì)存儲(chǔ)于對(duì)應(yīng)的域?qū)ο螽?dāng)中

prototype scope 不會(huì)存儲(chǔ),需要自己找到此對(duì)象銷(xiāo)毀

存儲(chǔ)時(shí)都會(huì)封裝為 DisposableBeanAdapter 類(lèi)型對(duì)銷(xiāo)毀方法的調(diào)用進(jìn)行適配。

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!