最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring創(chuàng)建Bean的關(guān)鍵流程分享

 更新時間:2026年04月07日 09:51:12   作者:Binary-Jeff  
Spring中的Bean生命周期從創(chuàng)建到銷毀分為多個階段,包括實(shí)例化、屬性填充、Aware回調(diào)、初始化前處理、初始化處理、初始化后處理、Bean就緒和銷毀,每個階段都有特定的任務(wù),例如屬性注入、初始化方法調(diào)用和資源釋放等,Spring通過三級緩存機(jī)制解決循環(huán)依賴問題

一、什么是 Bean 生命周期?

簡單來說,Bean 生命周期就是:

一個 Bean 從創(chuàng)建 → 初始化 → 使用 → 銷毀的完整過程

換句話說:

  • 對象什么時候創(chuàng)建?
  • 依賴什么時候注入?
  • 初始化邏輯什么時候執(zhí)行?
  • 什么時候被銷毀?

全部由 Spring 控制,而不是開發(fā)者手動管理。

二、Bean 生命周期整體流程

一個完整的 Bean 生命周期可以抽象為:

實(shí)例化 → 屬性填充 → 初始化 → 使用 → 銷毀

但如果展開來看,其實(shí)遠(yuǎn)比這復(fù)雜:

1. 實(shí)例化 Bean

Spring 通過反射創(chuàng)建 Bean 對象(調(diào)用構(gòu)造方法),此時只是“空對象”,還沒有屬性值(Bean 中的成員變量(字段)所對應(yīng)的值)。

關(guān)鍵點(diǎn):只執(zhí)行構(gòu)造方法,依賴還沒注入

2. 屬性填充(依賴注入)

Spring 根據(jù)配置(XML / 注解如 @Autowired)為 Bean 注入依賴屬性。

關(guān)鍵點(diǎn):完成對象之間的依賴關(guān)系綁定

可能會存在循環(huán)依賴處理,下來會有一篇專門講如何解決

3. Aware 接口回調(diào)

如果 Bean 實(shí)現(xiàn)了 BeanNameAware、BeanFactoryAwareApplicationContextAware 等接口,  Spring 會回調(diào)這些方法,把容器相關(guān)信息注入進(jìn)去。

關(guān)鍵點(diǎn):讓 Bean “感知” Spring 容器(拿到 BeanName、容器對象等)

4. BeanPostProcessor 前置處理

所有注冊的 BeanPostProcessor 會在初始化前執(zhí)行 postProcessBeforeInitialization() 方法,對 Bean 進(jìn)行增強(qiáng)或修改。

關(guān)鍵點(diǎn):可以對 Bean 做“初始化前加工”(例如修改屬性)

5. 初始化(InitializingBean / init-method)

執(zhí)行 Bean 的初始化邏輯,比如:

  • afterPropertiesSet()(實(shí)現(xiàn) InitializingBean)
  • 自定義 init-method

 關(guān)鍵點(diǎn):開發(fā)者定義的“初始化完成后要做的事”

6. BeanPostProcessor 后置處理(AOP在這里)

執(zhí)行 postProcessAfterInitialization() 方法,這一步常用于生成代理對象(比如 AOP)。

關(guān)鍵點(diǎn):

  • AOP 動態(tài)代理在這里產(chǎn)生
  • 返回的可能已經(jīng)不是原始 Bean,而是代理對象

7. Bean 就緒可用

 Bean 完成所有處理,進(jìn)入容器緩存(單例池),可以被應(yīng)用程序正常使用。

 關(guān)鍵點(diǎn):

  • 從這里開始,你 getBean() 拿到的就是最終對象(可能是代理對象)

8. 容器關(guān)閉 → 銷毀

 當(dāng)容器關(guān)閉時,執(zhí)行 Bean 的銷毀方法:

  • destroy()(實(shí)現(xiàn) DisposableBean)
  • 自定義 destroy-method

關(guān)鍵點(diǎn):釋放資源(連接、線程、文件等)

三、核心流程詳解

1. 實(shí)例化 Bean

Spring 在創(chuàng)建 Bean 時,首先會通過反射實(shí)例化對象,其核心邏輯位于 createBeanInstance 方法中:

Object bean = beanClass.newInstance();

更底層:

Constructor<?> constructor = clazz.getDeclaredConstructor();
bean = constructor.newInstance();

此時:

  • 只是一個“空對象”
  • 屬性還沒有注入
  • 依賴關(guān)系還沒建立

這一階段的本質(zhì),僅僅是在 JVM 堆中創(chuàng)建了一個對象實(shí)例。此時的 Bean 還沒有任何依賴關(guān)系,屬性值也全部為默認(rèn)值,可以理解為一個“空殼對象”。

Spring 并不會簡單停留在這里,而是在實(shí)例化之后立即執(zhí)行一個非常關(guān)鍵的操作——提前暴露 Bean 引用

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

這一步的作用是將當(dāng)前 Bean 的“早期引用”放入三級緩存中,從而為后續(xù)可能發(fā)生的循環(huán)依賴提供解決基礎(chǔ)。

2. 屬性填充(依賴注入)

在實(shí)例化完成之后,Spring 會進(jìn)入依賴注入階段:

populateBean(beanName, mbd, instanceWrapper);

在這個過程中,Spring 會解析 Bean 中的依賴(如 @Autowired、@Resource),并通過 resolveDependency 方法遞歸查找或創(chuàng)建依賴對象,最終通過反射完成注入:

Object dependency = resolveDependency(...); 
field.set(bean, dependency);

關(guān)鍵點(diǎn):

  • 這里會觸發(fā) 依賴查找
  • 循環(huán)依賴問題正是發(fā)生在這里!我們可以發(fā)現(xiàn),循環(huán)依賴產(chǎn)生的根本原因在于:Bean 之間的依賴關(guān)系是在初始化完成之前建立的。

3. Aware 接口回調(diào)(容器能力注入)

當(dāng)依賴注入完成后,Spring 會執(zhí)行一系列 Aware 接口回調(diào),其核心邏輯位于:

invokeAwareMethods(beanName, bean);

Spring 會判斷 Bean 是否實(shí)現(xiàn)了 BeanNameAware、BeanFactoryAware、ApplicationContextAware 等接口,并調(diào)用對應(yīng)方法,例如:

((BeanNameAware) bean).setBeanName(beanName);

這一階段的設(shè)計目的,是讓 Bean 可以“感知”容器的存在,從而具備獲取上下文信息的能力。

一句話總結(jié):開發(fā)者可以主動從 Spring 容器里“拿東西”,而不是等容器注入

例如,開發(fā)者可以通過 ApplicationContext 手動獲取其他 Bean

ApplicationContext context = ...;
UserService userService = context.getBean("userService");

從設(shè)計角度來看,這是一種典型的“控制反轉(zhuǎn)中的反向注入”。

4. 初始化前處理(BeanPostProcessor 前置增強(qiáng))

在正式初始化之前,Spring 會執(zhí)行 BeanPostProcessor 的前置方法,其源碼如下:

applyBeanPostProcessorsBeforeInitialization(bean, beanName);

底層實(shí)現(xiàn)是遍歷所有 BeanPostProcessor:

for (BeanPostProcessor processor : processors) {
    bean = processor.postProcessBeforeInitialization(bean, beanName);
}

BeanPostProcessor 的前置處理方法是在初始化方法執(zhí)行之前調(diào)用的,主要用于對 Bean 進(jìn)行統(tǒng)一的增強(qiáng)、修改或預(yù)處理,屬于 Spring 提供的擴(kuò)展機(jī)制;而 @PostConstruct 等初始化方法則是開發(fā)者定義的,用于完成 Bean 自身的初始化邏輯。兩者的主要區(qū)別在于職責(zé)不同,一個偏框架擴(kuò)展,一個偏業(yè)務(wù)初始化。

5. 初始化階段(Bean 完整構(gòu)建)

在前置處理完成后,Spring 會進(jìn)入真正的初始化階段,其核心方法為:

invokeInitMethods(beanName, bean, mbd);

Spring 支持多種初始化方式,例如實(shí)現(xiàn) InitializingBean 接口:

afterPropertiesSet();

或者通過配置 init-method

<bean init-method="init"/>

BeanPostProcessor 前置處理主要用于對 Bean 進(jìn)行統(tǒng)一的增強(qiáng)或修改,屬于框架級擴(kuò)展機(jī)制;而初始化階段(如 @PostConstruct 或 afterPropertiesSet)則由開發(fā)者定義,用于完成 Bean 的業(yè)務(wù)初始化邏輯,使其具備實(shí)際可用性。兩者的區(qū)別在于,前者側(cè)重于“加工 Bean”,后者側(cè)重于“使用 Bean”。

這一階段的本質(zhì),是對 Bean 做最后的“加工處理”,例如參數(shù)校驗(yàn)、資源加載、連接初始化等??梢哉J(rèn)為,Bean 在這里才真正具備“業(yè)務(wù)可用性”。

6. 初始化后處理(AOP 代理生成關(guān)鍵階段)

初始化完成后,Spring 會再次執(zhí)行 BeanPostProcessor,但這一次是后置處理:

applyBeanPostProcessorsAfterInitialization(bean, beanName);

其核心邏輯通常表現(xiàn)為:

return wrapIfNecessary(bean);

這一階段是 Spring AOP 實(shí)現(xiàn)的關(guān)鍵入口。如果 Bean 滿足切面條件(如被 @Transactional、@Aspect 等增強(qiáng)),Spring 會在這里為其創(chuàng)建代理對象(JDK 動態(tài)代理或 CGLIB)。因此,最終放入容器中的對象,很可能已經(jīng)不是原始對象,而是一個代理對象。這一點(diǎn)在理解循環(huán)依賴時尤為重要,因?yàn)?ldquo;提前暴露”的對象必須與最終對象保持一致,否則會導(dǎo)致代理失效問題。

總結(jié):在 Spring 中,如果 Bean 被 AOP 增強(qiáng),那么容器中最終存儲的并不是原始對象,而是其代理對象,BeanName 不發(fā)生變化。開發(fā)者通過依賴注入或 getBean 獲取到的也是該代理對象。原始對象只在 Bean 創(chuàng)建過程中短暫存在,不會被放入一級緩存,也不會被直接使用。

7. Bean 就緒(進(jìn)入容器,可被使用)

當(dāng)上述所有步驟完成后,Bean 會被放入單例緩存中(singletonObjects),正式成為容器中的一個可用組件。此時 Bean 已經(jīng)完成了依賴注入、初始化以及可能的 AOP 增強(qiáng),可以被其他 Bean 或業(yè)務(wù)代碼正常獲取:

context.getBean(A.class);

從生命周期角度來看,這一階段是 Bean 存在時間最長、最穩(wěn)定的階段。

8. Bean 銷毀(生命周期終點(diǎn))

當(dāng) Spring 容器關(guān)閉時(例如調(diào)用 context.close()),會觸發(fā) Bean 的銷毀流程。

其核心邏輯包括:

DisposableBean.destroy();

以及:

@PreDestroy

或:

<bean destroy-method="destroy"/>

這一階段主要用于釋放資源,例如關(guān)閉數(shù)據(jù)庫連接、線程池、網(wǎng)絡(luò)連接等。從設(shè)計角度來看,這是對資源管理的一種“兜底機(jī)制”,確保系統(tǒng)優(yōu)雅關(guān)閉。

四、總結(jié)

從整體來看,Spring 中的 Bean 生命周期本質(zhì)上是一個“逐步加工對象”的過程。

從源碼執(zhí)行順序來看,這一過程可以概括為:實(shí)例化 → 提前暴露 → 依賴注入 → 初始化 → AOP增強(qiáng) → 使用 → 銷毀。其中一個非常關(guān)鍵的細(xì)節(jié)在于:依賴注入發(fā)生在初始化之前,而 Bean 在實(shí)例化之后就已經(jīng)被提前暴露。這意味著,一個 Bean 在尚未完全構(gòu)建完成時,就有可能被其他 Bean 所引用。

正是這一設(shè)計,引出了一個經(jīng)典且不可避免的問題:如果兩個 Bean 之間存在相互依賴關(guān)系(如 A 依賴 B,B 又依賴 A),那么在依賴注入階段就會出現(xiàn)“對象尚未完成初始化卻被再次請求”的情況。這種現(xiàn)象就是所謂的循環(huán)依賴問題。

那么,Spring 是如何在允許這種“半成品對象被引用”的前提下,仍然保證系統(tǒng)正常運(yùn)行的?又是如何避免無限遞歸創(chuàng)建的?這正是下一步需要深入分析的核心——基于三級緩存的循環(huán)依賴解決機(jī)制。

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java中的instanceof關(guān)鍵字詳細(xì)解讀

    java中的instanceof關(guān)鍵字詳細(xì)解讀

    這篇文章主要介紹了java中的instanceof關(guān)鍵字詳細(xì)解讀,instanceof 是 Java 的保留關(guān)鍵字,它的作用是測試它左邊的對象是否是它右邊的類的實(shí)例,返回 boolean 的數(shù)據(jù)類型,需要的朋友可以參考下
    2024-01-01
  • java關(guān)鍵字super的騷操作詳解

    java關(guān)鍵字super的騷操作詳解

    關(guān)鍵字super在Java中用于引用當(dāng)前類的父類(即超類)的構(gòu)造方法、訪問父類的成員變量和方法,它提供了一種方便的方式來處理繼承關(guān)系中的父類操作,下面我們就來看看它有哪些騷操作吧
    2023-09-09
  • SpringBoot+POI實(shí)現(xiàn)給word添加水印功能

    SpringBoot+POI實(shí)現(xiàn)給word添加水印功能

    這篇文章主要介紹了SpringBoot+POI實(shí)現(xiàn)給word添加水印功能,文中通過代碼示例講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • springcloud之自定義簡易消費(fèi)服務(wù)組件

    springcloud之自定義簡易消費(fèi)服務(wù)組件

    這篇文章主要介紹了springcloud之自定義簡易消費(fèi)服務(wù)組件,本篇來使用rest+ribbon消費(fèi)服務(wù),并且通過輪詢方式來自定義了個簡易消費(fèi)組件,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 在 Spring Boot 項目中使用分頁插件的兩種常見方式示例詳解

    在 Spring Boot 項目中使用分頁插件的兩種常見方式示例詳解

    本文介紹了SpringBoot項目中兩種分頁插件的使用方法:MyBatis-Plus分頁插件和PageHelper插件,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-10-10
  • Java 高并發(fā)五:JDK并發(fā)包1詳細(xì)介紹

    Java 高并發(fā)五:JDK并發(fā)包1詳細(xì)介紹

    本文主要介紹 Java高并發(fā)JDK并發(fā)包1的資料,這里對1.各種同步控制工具的使用 2.并發(fā)容器及典型源碼分析,有需要的小伙伴可以參考下
    2016-09-09
  • idea環(huán)境下Maven無法正常下載pom中配置的包問題

    idea環(huán)境下Maven無法正常下載pom中配置的包問題

    這篇文章主要介紹了idea環(huán)境下Maven無法正常下載pom中配置的包的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Spring工程中集成多個redis數(shù)據(jù)源的思路詳解

    Spring工程中集成多個redis數(shù)據(jù)源的思路詳解

    Spring項目集成雙Redis數(shù)據(jù)源需配置兩個連接工廠與RedisTemplate,通過@Primary指定默認(rèn)Bean,@Qualifier注入特定Bean,支持集群環(huán)境,本文給大家介紹Spring工程中集成多個redis數(shù)據(jù)源的相關(guān)知識,感興趣的朋友一起看看吧
    2025-07-07
  • SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT)

    SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT)

    本文主要介紹了SpringSecurity角色權(quán)限控制(SpringBoot+SpringSecurity+JWT),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • 詳解Mybatis的二級緩存配置

    詳解Mybatis的二級緩存配置

    這篇文章主要介紹了Mybatis的二級緩存配置的相關(guān)資料,需要的朋友可以參考下
    2017-05-05

最新評論

海林市| 正定县| 古田县| 水城县| 蒙阴县| 朝阳市| 如皋市| 庄浪县| 松江区| 改则县| 金秀| 沙河市| 霍林郭勒市| 桓台县| 肥东县| 安吉县| 逊克县| 河津市| 黔江区| 张家港市| 苍南县| 永州市| 青州市| 鸡东县| 长海县| 宁化县| 正阳县| 瓦房店市| 湖南省| 岳普湖县| 弥勒县| 尼玛县| 苗栗县| 安丘市| 朝阳县| 洪泽县| 舒兰市| 广宗县| 同仁县| 双辽市| 清水县|