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

Spring bean生命周期分為幾個階段?

更新時間:2022-08-15 來源:黑馬程序員 瀏覽量:

IT培訓(xùn)班

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

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

劃分的階段和名稱并不重要,重要的是理解整個過程中做了哪些事情。

1. 處理名稱,檢查緩存

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

里針對單例對象會檢查一級、二級、三級緩存。

singletonFactories 三級緩存,存放單例工廠對象。

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

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

singletonObjects 一級緩存,存放單例成品對象。

2. 處理父子容器

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

3. 處理 dependsOn

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

4. 選擇 scope 策略

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

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

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

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

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

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

5.4 創(chuàng)建 bean - 注冊可銷毀 bean

在這一步判斷并登記可銷毀 bean

判斷依據(jù)

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

如果自定義了 destroyMethod,則為可銷毀 bean

如果采用 @Bean 沒有指定 destroyMethod,則采用自動推斷方式獲取銷毀方法名(close,shutdown)

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

存儲位置

singleton scope 的可銷毀 bean 會存儲于 beanFactory 的成員當(dāng)中

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

prototype scope 不會存儲,需要自己找到此對象銷毀

存儲時都會封裝為 DisposableBeanAdapter 類型對銷毀方法的調(diào)用進行適配。

分享到:
在線咨詢 我要報名
和我們在線交談!