更新時間:2022-08-15 來源:黑馬程序員 瀏覽量:
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. 處理父子容器
如果當前容器根據(jù)名字找不到這個 bean,此時若父容器存在,則執(zhí)行父容器的 getBean 流程。父子容器的 bean 名稱可以重復(fù)。
3. 處理 dependsOn
如果當前 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 標注的方法
存儲位置
singleton scope 的可銷毀 bean 會存儲于 beanFactory 的成員當中
自定義 scope 的可銷毀 bean 會存儲于對應(yīng)的域?qū)ο螽斨?/p>
prototype scope 不會存儲,需要自己找到此對象銷毀
存儲時都會封裝為 DisposableBeanAdapter 類型對銷毀方法的調(diào)用進行適配。