更新時(shí)間:2022-08-15 來源:黑馬程序員 瀏覽量:
bean 的生命周期從調(diào)用 beanFactory 的 getBean 開始,到這個(gè) bean 被銷毀,可以總結(jié)為以下七個(gè)階段:
處理名稱,檢查緩存→處理父子容器→處理 dependsOn→選擇 scope 策略→創(chuàng)建 bean→類型轉(zhuǎn)換處理→銷毀 bean
劃分的階段和名稱并不重要,重要的是理解整個(gè)過程中做了哪些事情。
1. 處理名稱,檢查緩存
這一步會(huì)處理別名,將別名解析為實(shí)際名稱。對(duì) FactoryBean 也會(huì)特殊處理,如果以 & 開頭表示要獲取 FactoryBean 本身,否則表示要獲取其產(chǎn)品。
里針對(duì)單例對(duì)象會(huì)檢查一級(jí)、二級(jí)、三級(jí)緩存。
singletonFactories 三級(jí)緩存,存放單例工廠對(duì)象。
earlySingletonObjects 二級(jí)緩存,存放單例工廠的產(chǎn)品對(duì)象。
如果發(fā)生循環(huán)依賴,產(chǎn)品是代理;無循環(huán)依賴,產(chǎn)品是原始對(duì)象。
singletonObjects 一級(jí)緩存,存放單例成品對(duì)象。
2. 處理父子容器
如果當(dāng)前容器根據(jù)名字找不到這個(gè) bean,此時(shí)若父容器存在,則執(zhí)行父容器的 getBean 流程。父子容器的 bean 名稱可以重復(fù)。
3. 處理 dependsOn
如果當(dāng)前 bean 有通過 dependsOn 指定了非顯式依賴的 bean,這一步會(huì)提前創(chuàng)建這些 dependsOn 的
bean,所謂非顯式依賴,就是指兩個(gè) bean 之間不存在直接依賴關(guān)系,但需要控制它們的創(chuàng)建先后順序。
4. 選擇 scope 策略
對(duì)于 singleton scope,首先到單例池去獲取 bean,如果有則直接返回,沒有再進(jìn)入創(chuàng)建流程。
對(duì)于 prototype scope,每次都會(huì)進(jìn)入創(chuàng)建流程。
對(duì)于自定義 scope,例如 request,首先到 request 域獲取 bean,如果有則直接返回,沒有再進(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 都沒找到構(gòu)造,采用默認(rèn)構(gòu)造,即使是私有的 |5.2 創(chuàng)建 bean - 依賴注入
| ------------------------------------ | ------------------------------------------------------------ | | 有自定義 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 都沒找到構(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 | 通過接口回調(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è)可銷毀 bean
在這一步判斷并登記可銷毀 bean
判斷依據(jù)
如果實(shí)現(xiàn)了 DisposableBean 或 AutoCloseable 接口,則為可銷毀 bean
如果自定義了 destroyMethod,則為可銷毀 bean
如果采用 @Bean 沒有指定 destroyMethod,則采用自動(dòng)推斷方式獲取銷毀方法名(close,shutdown)
如果有 @PreDestroy 標(biāo)注的方法
存儲(chǔ)位置
singleton scope 的可銷毀 bean 會(huì)存儲(chǔ)于 beanFactory 的成員當(dāng)中
自定義 scope 的可銷毀 bean 會(huì)存儲(chǔ)于對(duì)應(yīng)的域?qū)ο螽?dāng)中
prototype scope 不會(huì)存儲(chǔ),需要自己找到此對(duì)象銷毀
存儲(chǔ)時(shí)都會(huì)封裝為 DisposableBeanAdapter 類型對(duì)銷毀方法的調(diào)用進(jìn)行適配。