Spring的Bean的生命周期 | 有圖有案例

Spring的Bean的生命周期

  • Spring的Bean的生命周期
    • 整體過程
    • 實例化
    • 初始化
    • 服務
    • 銷毀
    • 循環依賴問題
  • 完整生命周期演示

Spring的Bean的生命周期

Spring Bean的生命周期:從Bean的實例化之后,通過反射創建出對象之后,到Bean稱為一個完整的對象,接著被存儲到singletonObjects中,最后被銷毀的全過程。

整體過程

過程劃分:整體劃分為四個階段

在這里插入圖片描述

Spring中Bean的創建實際上是在createBean方法中完成,但實際底層工作的是doCreateBean方法;方法所在的位置AbstractAutowireCapableBeanFactory中的doCreateBean,這里面存放的實際上存放的就是Bean生命周期的整個過程。

// AbstractAutowireCapableBeanFactory.java
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)throws BeanCreationException {// 1. beanWrapper是實例化bean的第一步BeanWrapper instanceWrapper = null;if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}Object exposedObject = bean;try {// 2. populateBean方法進行屬性賦值populateBean(beanName, mbd, instanceWrapper);// 3. 調用initilizeBean進行spring初始化(省略了詳細的代碼步驟)exposedObject = initializeBean(beanName, exposedObject, mbd);}// 4. 銷毀try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}return exposedObject;
}

實例化

實例化過程:Spring框架會取出BeanDefinition的信息進行判斷當前Bean的范圍是否是singleton的, 是否不是延遲加載的,是否不是FactoryBean等,最終將一個普通的singleton的Bean通過反射進行實例化;這個過程實際上是JVM在做,對象的創建過程可以參考之前寫的Java對象的創建過程里面有詳細的講解。

初始化

初始化:Bean創建之后還僅僅是個"半成品",還需要對Bean實例的屬性進行填充、執行一些Aware 接口方法、執行BeanPostProcessor方法、執行InitializingBean接口的初始化方法、執行自定義初始化init方法等。具體的流程如下:

  1. 屬性注入:

    1. 注入普通屬性,String、int或存儲基本類型的集合時,直接通過set方法的反射設置進去;
    2. 注入單向對象引用屬性時,從容器中getBean獲取后通過set方法反射設置進去,如果容器中沒有,則先創建被注入對象Bean實例(完成整個生命周期)后,在進行注入操作
    3. 注入雙向對象引用屬性時,就比較復雜了,涉及了循環引用(循環依賴)
  2. BeanNameAware的setBeanName():

    如果Bean類有實現org.springframework.beans.BeanNameAware接口,工廠調用Bean的setBeanName()方法傳遞Bean的ID。

  3. BeanFactoryAware的setBeanFactory():

    如果Bean類有實現org.springframework.beans.factory.BeanFactoryAware接口,工廠調用setBeanFactory()方法傳入工廠自身。

  4. BeanPostProcessors的ProcessBeforeInitialization():

    如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean關聯,那么其postProcessBeforeInitialization()方法將被將被調用。

  5. initializingBean的afterPropertiesSet():

    如果Bean類已實現org.springframework.beans.factory.InitializingBean接口,則執行他的afterProPertiesSet()方法。

  6. Bean定義文件中定義init-method:

    如果配置文件中使用init-method屬性指定了初始化方法,那么Bean在實例化完成后將會調用該屬性指定的初始化方法進行Bean的初始化。

  7. BeanPostProcessors的ProcessaAfterInitialization():

    如果有任何的BeanPostProcessors實例與Bean實例關聯,則執行BeanPostProcessors實例的ProcessaAfterInitialization()方法。

服務

服務:使用階段。

銷毀

銷毀:當Bean不再需要時,會經過清理階段,如果Bean實現了DisposableBean這個接口,會調用那個其實現的destroy()方法;如果這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷毀方法。

循環依賴問題

注入雙向對象引用屬性時就會出現循環依賴

循環依賴:多個實體之間相互依賴并形成閉環的情況就叫做"循環依賴",也叫做"循環引用"

在這里插入圖片描述

循環依賴問題spring已經給出了解決方法:三級緩存

Spring提供了三級緩存存儲 完整Bean實例 和 半成品Bean實例 ,用于解決循環引用問題

在DefaultListableBeanFactory的上四級父類DefaultSingletonBeanRegistry中提供如下三個Map

在這里插入圖片描述

假如,UserService注入了一個UserDao,UserDao又注入了一個UserService,實例化過程如下:

  • UserService 實例化對象,但尚未初始化,將UserService存儲到三級緩存
  • UserService 屬性注入,需要UserDao,從緩存中獲取,沒有UserDao
  • UserDao實例化對象,但尚未初始化,將UserDao存儲到到三級緩存
  • UserDao屬性注入,需要UserService,從三級緩存獲取UserService,UserService從三級緩存移入二級緩存
  • UserDao執行其他生命周期過程,最終成為一個完成Bean,存儲到一級緩存,刪除二三級緩存
  • UserService 注入UserDao
  • UserService執行其他生命周期過程,最終成為一個完成Bean,存儲到一級緩存,刪除二三級緩存

完整生命周期演示

  1. 導入坐標:spring context

  2. 創建實體類:Student,實現接口:

    InitializingBean,BeanFactoryAware,BeanNameAware,ApplicationContextAware

    public class Student implements InitializingBean,BeanFactoryAware,BeanNameAware,ApplicationContextAware{private String sname;public Student() {System.out.println("bean的無參構造方法");}public void setSname(String sname) {System.out.println("set方法賦值");this.sname = sname;}public void doinit(){System.out.println("方法初始化");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("接口的初始化方法");}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("BeanFactoryAware接口");}@Overridepublic void setBeanName(String s) {System.out.println("BeanNameAware接口");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("ApplicationContextAware接口");}
    }
    
  3. 創建bean后處理類

    public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean的后處理的postProcessBeforeInitialization方法");return null;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean的后處理的postProcessAfterInitialization方法");return null;}
    }
    
  4. spring主配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="student" class="com.dong.bean.Student" init-method="doinit"><property name="sname" value="張三"></property></bean><bean id="beanPostProcessor" class="com.dong.provessor.MyBeanPostProcessor"></bean></beans>
    
  5. 測試:getBean注入的Student

    public class Test01 {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Student student = (Student) applicationContext.getBean("student");System.out.println("bean的實例對象:" + student);}
    }
    
  6. 輸入結果,順序如下:

    bean的無參構造方法
    set方法賦值
    BeanNameAware接口
    BeanFactoryAware接口
    ApplicationContextAware接口
    Bean的后處理的postProcessBeforeInitialization方法
    接口的初始化方法
    方法初始化
    Bean的后處理的postProcessAfterInitialization方法
    bean的實例對象:com.li.bean.Student@6536e911

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/718648.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/718648.shtml
英文地址,請注明出處:http://en.pswp.cn/news/718648.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

EXPLAIN:mysql 執行計劃分析詳解

目錄 EXPLAIN命令 查看執行計劃 分析執行計劃 優化查詢 EXPLAIN中的 type 列類型 在MySQL中&#xff0c;你可以使用EXPLAIN命令來生成查詢的執行計劃。EXPLAIN命令可以顯示MySQL如何使用鍵來處理SELECT和DELETE語句&#xff0c;以及INSERT或UPDATE語句的WHERE子句。這對于…

SRS Stack提供的鑒權、私人直播間、多平臺轉播、錄制等高級功能的具體使用方法是什么?

SRS Stack提供的鑒權、私人直播間、多平臺轉播、錄制等高級功能的具體使用方法是什么&#xff1f; 鑒權功能&#xff1a;SRS Stack支持通過系統配置中的OpenAPI獲取Bearer鑒權&#xff0c;并可以嘗試HTTP API。用戶可以通過點擊網頁上的按鈕請求HTTP API&#xff0c;或者使用cu…

快上車:什么是人工智能?人工智能和普通程序的區別

什么是人工智能&#xff1f; 雖然AI歷史很悠久&#xff0c;上個世紀50年代就有各種概念&#xff0c;但是發展很慢。第一次對人類的沖擊就是1997年IBM深藍擊敗國際象棋世界冠軍&#xff0c;引起了人們的廣泛關注&#xff0c;之后又銷聲匿跡。突然間2016人工智能alphaGO戰勝了圍…

具身智能計算系統,機器人時代的 Android | 新程序員

【導讀】具身智能作為一種新興的研究視角和方法論&#xff0c;正在刷新我們對智能本質及其發展的理解&#xff1a;傳統的 AI 模型往往將智能視為一種獨立于實體存在的抽象能力&#xff0c;而具身智能則主張智能是實體與其環境持續互動的結果。 本文深度剖析了具身智能計算系統…

【CSS】初學了解Grid布局

目錄 什么是Grid布局如何開始使用Grid布局Grid容器的屬性Grid項目的屬性舉個例子 什么是Grid布局 Grid布局是一種二維的布局系統&#xff0c;它允許我們在水平和垂直方向上同時控制網格中的項目位置。通過將頁面劃分為行和列&#xff0c;我們可以輕松地創建出復雜的布局結構&a…

程序員如何選擇職業賽道?

一、自我評估與興趣探索 程序員選擇職業賽道時&#xff0c;可以考慮以下幾個關鍵因素&#xff1a; 1、興趣與熱情&#xff1a;首先要考慮自己的興趣和熱情&#xff0c;選擇符合個人喜好和激情的領域&#xff0c;能夠激勵自己持續學習和進步。 2、技術能力&am…

2.python72變筆記(自用未修改版)

以前寫的python筆記 1.二進制與字符編碼 #8bit&#xff08;位&#xff09;1byte&#xff08;字節&#xff09; #1024byte 1KB 千字節 #1024KB 1MB 兆字節 #1024MB 1TB 太字節 print(chr(0b100111001010000)) print(ord("陳")) #ord 十進制 #無論英語還是漢語在計算…

mysql5.7配置主從

原理&#xff1a; MySQL主從復制的工作原理如下:1. 主服務器產生Binlog日志當主服務器的數據庫發生數據修改操作時,如INSERT、UPDATE、DELETE語句執行,主服務器會記錄這些操作的日志信息到二進制日志文件中。2. 從服務器讀取Binlog日志 從服務器會向主服務器發送請求,主服務器把…

微信小程序開發學習筆記《18》uni-app框架-網絡請求與輪播圖

微信小程序開發學習筆記《18》uni-app框架-網絡請求 博主正在學習微信小程序開發&#xff0c;希望記錄自己學習過程同時與廣大網友共同學習討論。建議仔細閱讀uni-app對應官方文檔 一、下載網絡請求包 這個包是以前黑馬程序員老師寫的一個包&#xff0c;跟著課程學習&#x…

Open3D(C++) 指定點數的體素濾波

目錄 一、算法原理1、算法過程2、參考文獻二、代碼實現三、結果展示本文由CSDN點云俠原創,原文鏈接。如果你不是在點云俠的博客中看到該文章,那么此處便是不要臉的爬蟲與GPT。 一、算法原理 1、算法過程 對于數據量較大的點云,在后期進行配準時會影響計算效率。而體素格網…

vue3ts websocket通信

前端&#xff1a;vue3ts 后端&#xff1a;springboot npm安裝依賴 cnpm install sockjs-client stompjs 前端代碼 <template><div><el-input v-model"message" type"text" placeholder"發送" /><el-button-group><…

LCR 170. 交易逆序對的總數

解題思路&#xff1a; 歸并排序&#xff0c;在歸并的過程中不斷計算逆序對的個數 count mid -i 1&#xff1b;的來源見下圖&#xff0c;因為兩個數組都是單調遞增的&#xff0c;所以如果第一個數組的前一個元素大于第二個數組的對應元素&#xff0c;那么第一個數組的這一元素…

借助Aspose.SVG圖像控件,在 C# 中將圖像轉換為 Base64

Base64 編碼是一種二進制到文本的編碼方案&#xff0c;可有效地將二進制數據轉換為 ASCII 字符&#xff0c;為數據交換提供通用格式。在某些情況下&#xff0c;我們可能需要將JPG或PNG圖像轉換為 Base64 字符串數據。在這篇博文中&#xff0c;我們將學習如何在 C# 中將圖像轉換…

分享經典、現代和前沿軟件工程課程

隨著信息技術的發展&#xff0c;軟件已經深入到人類社會生產和生活的各個方面。軟件工程是將工程化的方法運用到軟件的開發、運行和維護之中&#xff0c;以達到提高軟件質量&#xff0c;降低開發成本的目的。軟件工程已經成為當今最活躍、最熱門的學科之一。 本次軟件工程MOOC課…

模板06-普通函數與函數模板調用規則

1、如果函數模板和普通函數都可以實現&#xff0c;優先調用普通函數 2、可以通過空模板參數列表來強調調用函數模板 3、函數模板也可以發生重載 4、如果函數模板可以發生更好的匹配&#xff0c;優先調用函數模板 #include <iostream> using namespace std;int my_add …

混合云技術架構是什么樣的

混合云技術架構是什么樣的&#xff1f;混合云技術架構是一種將公有云和私有云相結合的云計算架構。它允許組織在私有云和公有云之間靈活地共享和遷移應用程序、數據和服務。 混合云技術架構的設計可以根據組織的需求和業務要求進行定制&#xff0c;通常包括以下組件&#xff1…

現在如何才能開通微信公眾號留言功能?

為什么公眾號沒有留言功能&#xff1f;2018年2月12日之后直到現在&#xff0c;新注冊公眾號的運營者會發現一個問題&#xff1a;無論是個人還是企業的公眾號&#xff0c;在后臺都找不到留言功能了。這對公眾號來說絕對是一個極差的體驗&#xff0c;少了一個這么重要的功能&…

萬村樂數字鄉村系統開源代碼:革命性引領,助推鄉村振興新篇章

如今&#xff0c;國際社會普遍認為信息化、數字化已是重大且不可逆轉的發展趨勢&#xff0c;如何讓廣大農村地區充分分享到這個發展帶來的紅利&#xff0c;從而提升農村的經濟活力&#xff0c;確保村民生活質量不斷優化&#xff0c;已然成為我們需要認真研究并積極解決的重大議…

Window下編寫的sh文件在Linux/Docker中無法使用

Window下編寫的sh文件在Linux/Docker中無法使用 一、sh文件目的1.1 初始狀態1.2 目的 二、過程與異常2.1 首先獲取標準ubuntu20.04 - 正常2.2 啟動ubuntu20.04容器 - 正常2.3 執行windows下寫的preInstall文件 - 報錯 三、檢查和處理3.1 評估異常3.2 處理異常3.3 調整后運行測試…

WebFlux的探索與實戰 - r2dbc的多表查詢

前言 在一個有數據庫的項目中&#xff0c;條件查詢與多表查詢總是同幽靈般如影隨形。 好久不見朋友們&#xff0c;我是forte。 本篇文章會以我的 個人經驗 來介紹下如何在 Spring WebFlux 中使用 Spring Data R2DBC 進行多表查詢。 這次我會以一個自己寫的項目作為基礎來為各…