女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Spring中Bean的生命周期是怎樣的?

jf_ro2CN3Fa ? 來源:樓仔 ? 作者:樓仔 ? 2022-10-11 15:08 ? 次閱讀

1. 基礎(chǔ)知識

1.1 什么是 IoC ?

1.2 Bean 生命周期

1.3 執(zhí)行流程

1.4 擴(kuò)展方法

2. 源碼解讀

2.1 代碼入口

2.2 實例化

2.3 屬性賦值

2.4 初始化

2.5 銷毀

3. 寫在最后

Spring Bean 的生命周期,面試時非常容易問,這不,前段時間就有個讀者去面試,因為不會回答這個問題,一面都沒有過。

如果只講基礎(chǔ)知識,感覺和網(wǎng)上大多數(shù)文章沒有區(qū)別,但是我又想寫得稍微深入一點。

考慮很多同學(xué)不喜歡看源碼,我就把文章分為 2 大部分,前面是基礎(chǔ)知識,主要方便大家面試和學(xué)習(xí) ,后面是源碼部分,對源碼感興趣的同學(xué)可以繼續(xù)往后面看。

不 BB,上文章目錄。

f4755436-4162-11ed-96c9-dac502259ad0.png

1. 基礎(chǔ)知識

1.1 什么是 IoC ?

IoC,控制反轉(zhuǎn),想必大家都知道,所謂的控制反轉(zhuǎn),就是把 new 對象的權(quán)利交給容器,所有的對象都被容器控制,這就叫所謂的控制反轉(zhuǎn)。

IoC 很好地體現(xiàn)了面向?qū)ο笤O(shè)計法則之一 —— 好萊塢法則:“別找我們,我們找你 ”,即由 IoC 容器幫對象找相應(yīng)的依賴對象并注入,而不是由對象主動去找。

理解好 IoC 的關(guān)鍵是要明確 “誰控制誰,控制什么,為何是反轉(zhuǎn)(有反轉(zhuǎn)就應(yīng)該有正轉(zhuǎn)了),哪些方面反轉(zhuǎn)了”。

f4936020-4162-11ed-96c9-dac502259ad0.png

誰控制誰,控制什么?

傳統(tǒng) Java SE 程序設(shè)計,我們直接在對象內(nèi)部通過 new 進(jìn)行創(chuàng)建對象,是程序主動去創(chuàng)建依賴對象。而 IoC 是由專門一個容器來創(chuàng)建這些對象,即由 IoC 容器來控制對象的創(chuàng)建。

誰控制誰?當(dāng)然是 IoC 容器控制了對象;

控制什么?主要控制了外部資源獲取(不只是對象,比如包括文件等)。

為何是反轉(zhuǎn),哪些方面反轉(zhuǎn)了?

有反轉(zhuǎn)就有正轉(zhuǎn),傳統(tǒng)應(yīng)用程序是由我們自己在對象中主動控制去直接獲取依賴對象,也就是正轉(zhuǎn),而反轉(zhuǎn)則是由容器來幫忙創(chuàng)建及注入依賴對象。

為何是反轉(zhuǎn)?因為由容器幫我們查找及注入依賴對象,對象只是被動的接受依賴對象,所以是反轉(zhuǎn);

哪些方面反轉(zhuǎn)了?依賴對象的獲取被反轉(zhuǎn)了。

1.2 Bean 生命周期

對 Prototype Bean 來說,當(dāng)用戶 getBean 獲得 Prototype Bean 的實例后,IOC 容器就不再對當(dāng)前實例進(jìn)行管理,而是把管理權(quán)交由用戶,此后再 getBean 生成的是新的實例。

所以我們描述 Bean 的生命周期,都是指的 Singleton Bean。

f51a6804-4162-11ed-96c9-dac502259ad0.png

Bean 生命周期過程:

實例化 :第 1 步,實例化一個 Bean 對象;

屬性賦值 :第 2 步,為 Bean 設(shè)置相關(guān)屬性和依賴;

初始化 :初始化的階段的步驟比較多,5、6 步是真正的初始化,第 3、4 步為在初始化前執(zhí)行,第 7 步在初始化后執(zhí)行,初始化完成之后,Bean 就可以被使用了;

銷毀 :第 8~10 步,第 8 步其實也可以算到銷毀階段,但不是真正意義上的銷毀,而是先在使用前注冊了銷毀的相關(guān)調(diào)用接口,為了后面第 9、10 步真正銷毀 Bean 時再執(zhí)行相應(yīng)的方法。

整個執(zhí)行流程稍微有些抽象,下面我們通過代碼,來演示執(zhí)行流程。

1.3 執(zhí)行流程

創(chuàng)建一個 LouzaiBean。

publicclassLouzaiBeanimplementsInitializingBean,BeanFactoryAware,BeanNameAware,DisposableBean{

/**
*姓名
*/
privateStringname;

publicLouzaiBean(){
System.out.println("1.調(diào)用構(gòu)造方法:我出生了!");
}

publicStringgetName(){
returnname;
}

publicvoidsetName(Stringname){
this.name=name;
System.out.println("2.設(shè)置屬性:我的名字叫"+name);
}

@Override
publicvoidsetBeanName(Strings){
System.out.println("3.調(diào)用BeanNameAware#setBeanName方法:我要上學(xué)了,起了個學(xué)名");
}

@Override
publicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{
System.out.println("4.調(diào)用BeanFactoryAware#setBeanFactory方法:選好學(xué)校了");
}

@Override
publicvoidafterPropertiesSet()throwsException{
System.out.println("6.InitializingBean#afterPropertiesSet方法:入學(xué)登記");
}

publicvoidinit(){
System.out.println("7.自定義init方法:努力上學(xué)ing");
}

@Override
publicvoiddestroy()throwsException{
System.out.println("9.DisposableBean#destroy方法:平淡的一生落幕了");
}

publicvoiddestroyMethod(){
System.out.println("10.自定義destroy方法:睡了,別想叫醒我");
}

publicvoidwork(){
System.out.println("Bean使用中:工作,只有對社會沒有用的人才放假。。");
}
}

自定義一個后處理器 MyBeanPostProcessor。

publicclassMyBeanPostProcessorimplementsBeanPostProcessor{

@Override
publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{
System.out.println("5.BeanPostProcessor.postProcessBeforeInitialization方法:到學(xué)校報名啦");
returnbean;
}

@Override
publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{
System.out.println("8.BeanPostProcessor#postProcessAfterInitialization方法:終于畢業(yè),拿到畢業(yè)證啦!");
returnbean;
}
}

applicationContext.xml 配置文件(部分)。





測試入口:

publicclassMyTest{
publicstaticvoidmain(String[]args){
ApplicationContextcontext=newClassPathXmlApplicationContext("classpath:applicationContext.xml");
LouzaiBeanlouzaiBean=(LouzaiBean)context.getBean("louzaiBean");
louzaiBean.work();
((ClassPathXmlApplicationContext)context).destroy();
}
}

執(zhí)行結(jié)果:

1.調(diào)用構(gòu)造方法:我出生了!
2.設(shè)置屬性:我的名字叫樓仔
3.調(diào)用BeanNameAware#setBeanName方法:我要上學(xué)了,起了個學(xué)名
4.調(diào)用BeanFactoryAware#setBeanFactory方法:選好學(xué)校了
5.BeanPostProcessor.postProcessBeforeInitialization方法:到學(xué)校報名啦
6.InitializingBean#afterPropertiesSet方法:入學(xué)登記
7.自定義init方法:努力上學(xué)ing
8.BeanPostProcessor#postProcessAfterInitialization方法:終于畢業(yè),拿到畢業(yè)證啦!
Bean使用中:工作,只有對社會沒有用的人才放假。。
9.DisposableBean#destroy方法:平淡的一生落幕了
10.自定義destroy方法:睡了,別想叫醒我

這個流程非常清晰,Bean 生命周期流程圖能完全對應(yīng)起來。

1.4 擴(kuò)展方法

我們發(fā)現(xiàn),整個生命周期有很多擴(kuò)展過程,大致可以分為 4 類:

Aware 接口:讓 Bean 能拿到容器的一些資源,例如 BeanNameAware 的 setBeanName() ,BeanFactoryAware 的 setBeanFactory()

后處理器:進(jìn)行一些前置和后置的處理,例如 BeanPostProcessor 的 postProcessBeforeInitialization()postProcessAfterInitialization()

生命周期接口:定義初始化方法和銷毀方法的,例如 InitializingBean 的 afterPropertiesSet() ,以及 DisposableBean 的 destroy()

配置生命周期方法:可以通過配置文件,自定義初始化和銷毀方法,例如配置文件配置的 init()destroyMethod()

2. 源碼解讀

注意:Spring 的版本是 5.2.15.RELEASE ,否則和我的代碼不一樣!!!

上面的知識,網(wǎng)上其實都有,下面才是我們的重頭戲,讓你跟著我走一遍代碼流程。

2.1 代碼入口

f52ef8d2-4162-11ed-96c9-dac502259ad0.pngf5592b2a-4162-11ed-96c9-dac502259ad0.png

這里需要多跑幾次,把前面的 beanName 跳過去,只看 louzaiBean。

f58a2bc6-4162-11ed-96c9-dac502259ad0.pngf5c39cc6-4162-11ed-96c9-dac502259ad0.png

進(jìn)入 doGetBean(),從 getSingleton() 沒有找到對象,進(jìn)入創(chuàng)建 Bean 的邏輯。

f5ded540-4162-11ed-96c9-dac502259ad0.pngf614cd62-4162-11ed-96c9-dac502259ad0.png

2.2 實例化

進(jìn)入 doCreateBean() 后,調(diào)用 createBeanInstance()。

f628265a-4162-11ed-96c9-dac502259ad0.png

進(jìn)入 createBeanInstance() 后,調(diào)用 instantiateBean()。

f63fbda6-4162-11ed-96c9-dac502259ad0.pngf65af058-4162-11ed-96c9-dac502259ad0.pngf6687e58-4162-11ed-96c9-dac502259ad0.pngf68253fa-4162-11ed-96c9-dac502259ad0.pngf6b7d0de-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,實例化 LouzaiBean。

f6ca7ec8-4162-11ed-96c9-dac502259ad0.png圖片

2.3 屬性賦值

再回到 doCreateBean(),繼續(xù)往后走,進(jìn)入 populateBean()。

這個方法非常重要,里面其實就是依賴注入的邏輯,不過這個不是我們今天的重點,大家如果對依賴注入和循環(huán)依賴感興趣,可以翻閱我之前的文章。

f6e63e56-4162-11ed-96c9-dac502259ad0.png

進(jìn)入 populateBean() 后,執(zhí)行 applyPropertyValues()

f701bd5c-4162-11ed-96c9-dac502259ad0.png

進(jìn)入 applyPropertyValues(),執(zhí)行 bw.setPropertyValues()

f70dedfc-4162-11ed-96c9-dac502259ad0.pngf737e12a-4162-11ed-96c9-dac502259ad0.pngf75d67a6-4162-11ed-96c9-dac502259ad0.pngf76e0f84-4162-11ed-96c9-dac502259ad0.png

進(jìn)入 processLocalProperty(),執(zhí)行 ph.setValue()。

f787e59e-4162-11ed-96c9-dac502259ad0.pngf7b03ee0-4162-11ed-96c9-dac502259ad0.pngf7cf9e52-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,給 LouzaiBean 賦值 name。

f7fd9c6c-4162-11ed-96c9-dac502259ad0.png

到這里,populateBean() 就執(zhí)行完畢,下面開始初始化 Bean。

2.4 初始化

我們繼續(xù)回到 doCreateBean(),往后執(zhí)行 initializeBean()。

f82a1116-4162-11ed-96c9-dac502259ad0.pngf847984e-4162-11ed-96c9-dac502259ad0.pngf8594698-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,給 LouzaiBean 設(shè)置 BeanName。

f873cdba-4162-11ed-96c9-dac502259ad0.png

回到 invokeAwareMethods()。

f8814026-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,給 LouzaiBean 設(shè)置 BeanFactory。

f8e5b308-4162-11ed-96c9-dac502259ad0.png

第一次回到 initializeBean() ,執(zhí)行下面邏輯。

f8f35ff8-4162-11ed-96c9-dac502259ad0.png

這里需要多循環(huán)幾次,找到 MyBeanPostProcessor 的策略方法。

f93dad38-4162-11ed-96c9-dac502259ad0.png

我們自己定義的后置處理方法。

f988cc32-4162-11ed-96c9-dac502259ad0.png

第二次回到 initializeBean() ,執(zhí)行下面邏輯。

f9b3dec2-4162-11ed-96c9-dac502259ad0.pngf9d8cf98-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,執(zhí)行 afterPropertiesSet()。

f9f65ab8-4162-11ed-96c9-dac502259ad0.png

返回 invokeInitMethods(),執(zhí)行下面邏輯。

fa1bbf24-4162-11ed-96c9-dac502259ad0.png

進(jìn)入 invokeCustomInitMethod(),執(zhí)行下面邏輯。

fa45b18a-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,執(zhí)行 init()。

fa716384-4162-11ed-96c9-dac502259ad0.png

第三次回到 initializeBean() ,執(zhí)行下面邏輯。

fa8e46ca-4162-11ed-96c9-dac502259ad0.pngfaa8e7a0-4162-11ed-96c9-dac502259ad0.png

我們自己定義的后置處理方法。

fb2152da-4162-11ed-96c9-dac502259ad0.png

到這里,初始化的流程全部結(jié)束,都是圍繞 initializeBean() 展開。

2.5 銷毀

當(dāng) louzaiBean 生成后,后面開始執(zhí)行銷毀操作,整個流程就比較簡單。

fb47debe-4162-11ed-96c9-dac502259ad0.pngfb5f720e-4162-11ed-96c9-dac502259ad0.pngfb80dbba-4162-11ed-96c9-dac502259ad0.pngfba80762-4162-11ed-96c9-dac502259ad0.pngfbcf11b8-4162-11ed-96c9-dac502259ad0.pngfbf49f1e-4162-11ed-96c9-dac502259ad0.pngfc20e506-4162-11ed-96c9-dac502259ad0.pngfc3fcb38-4162-11ed-96c9-dac502259ad0.pngfc6ac6b2-4162-11ed-96c9-dac502259ad0.pngfc820aac-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,執(zhí)行 destroy()。

fca82fb6-4162-11ed-96c9-dac502259ad0.png

回到 destroy(),執(zhí)行下面邏輯。

fcc53da4-4162-11ed-96c9-dac502259ad0.pngfcfc5582-4162-11ed-96c9-dac502259ad0.pngfd9e5bac-4162-11ed-96c9-dac502259ad0.png

走進(jìn)示例 LouzaiBean 的方法,執(zhí)行 destroyMethod()。

fdd07268-4162-11ed-96c9-dac502259ad0.png

到這里,所有的流程全部結(jié)束,文章詳細(xì)描述所有的代碼邏輯流轉(zhuǎn),你可以完全根據(jù)上面的邏輯,自己 debug 一遍。

3. 寫在最后

我們再回顧一下幾個重要的方法:

doCreateBean() :這個是入口;

createBeanInstance() :用來初始化 Bean,里面會調(diào)用對象的構(gòu)造方法;

populateBean() :屬性對象的依賴注入,以及成員變量初始化;

initializeBean() :里面有 4 個方法,

先執(zhí)行 aware 的 BeanNameAware、BeanFactoryAware 接口;

再執(zhí)行 BeanPostProcessor 前置接口;

然后執(zhí)行 InitializingBean 接口,以及配置的 init();

最后執(zhí)行 BeanPostProcessor 的后置接口。

destory() :先執(zhí)行 DisposableBean 接口,再執(zhí)行配置的 destroyMethod()。

對于 populateBean(),里面的核心其實是對象的依賴注入,這里也是常考的知識點,比如循環(huán)依賴,大家如果對這塊也感興趣,可以和我交流。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • JAVA
    +關(guān)注

    關(guān)注

    20

    文章

    2984

    瀏覽量

    106795
  • 編程
    +關(guān)注

    關(guān)注

    88

    文章

    3679

    瀏覽量

    94840
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14874
  • IOC
    IOC
    +關(guān)注

    關(guān)注

    0

    文章

    28

    瀏覽量

    10288

原文標(biāo)題:阿里云面試:Spring 中 Bean 的生命周期是怎樣的?

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦
    熱點推薦

    基于Rust語言中的生命周期

    Rust是一門系統(tǒng)級編程語言具備高效、安和并發(fā)等特,而生命周期是這門語言中比較重要的概念之一。在這篇教程,我們會了解什么是命周期、為什么需要生命周期、如何使用
    的頭像 發(fā)表于 09-19 17:03 ?1074次閱讀

    KaihongOS操作系統(tǒng):頁面的生命周期介紹

    頁面的生命周期 在KaihongOS,學(xué)習(xí)頁面的生命周期前需要先了解自定義組件。 1. 自定義組件(Component) 自定義組件是通過@Component裝飾的UI單元,可以組合多個系統(tǒng)
    發(fā)表于 04-25 08:18

    ServiceAbility的生命周期介紹

    ServiceAbility的生命周期 開發(fā)者可以根據(jù)業(yè)務(wù)場景重寫生命周期相關(guān)接口。ServiceAbility生命周期接口說明見下表。 表1 ServiceAbility生命周期
    發(fā)表于 05-28 08:22

    Spring-10-bean生命周期

    spring
    電子學(xué)習(xí)
    發(fā)布于 :2023年01月07日 16:48:18

    09-SpringBean生命周期總結(jié)

    spring
    電子學(xué)習(xí)
    發(fā)布于 :2023年01月14日 09:55:54

    AutoScaling 生命周期掛鉤功能

    實例是伸縮組彈出來的不是手動添加的),然后釋放實例(如果 ECS 實例是伸縮組彈出來的不是手動添加的),并將實例從伸縮組移出。LifecycleHook 通知方式如果生命周期掛鉤配置了通知對象,那么
    發(fā)表于 06-27 17:13

    HarmonyOS應(yīng)用開發(fā)-PageAbility生命周期

    pageAbility的生命周期如下圖所示:在代碼通過調(diào)用下列方法實現(xiàn)生命周期操作:onShow() :Ability由后臺不可見狀態(tài)切換到前臺可見狀態(tài)調(diào)用onShow方法,此時用戶在屏幕可以看到
    發(fā)表于 10-17 11:11

    在S32G2 RM中有“生命周期”,生命周期的完整含義是什么?

    在S32G2 RM,有“生命周期”。生命周期的完整含義是什么,我們應(yīng)該如何使用它?
    發(fā)表于 04-23 10:37

    一文讀懂Android Activity生命周期

    正常情況下Activity的生命周期: Activity的生命周期大概可以歸為三部分 整個的生命周期:onCreate()可以設(shè)置所有的“全局”狀態(tài), onDestory()可以釋放所有的資源 可見
    發(fā)表于 05-30 01:03 ?1697次閱讀

    bean放入Spring容器中有哪些方式

    bean放入Spring容器中有哪些方式?
    的頭像 發(fā)表于 09-19 15:25 ?865次閱讀

    Vue入門Vue的生命周期

    .生命周期 4.1生命周期是什么 Vue的生命周期, 就是Vue實例從創(chuàng)建到銷毀的過程.
    的頭像 發(fā)表于 02-06 16:16 ?1006次閱讀
    Vue入門Vue的<b class='flag-5'>生命周期</b>

    編譯器的標(biāo)準(zhǔn)生命周期

    編譯器的標(biāo)準(zhǔn)生命周期
    發(fā)表于 03-14 19:06 ?0次下載
    編譯器的標(biāo)準(zhǔn)<b class='flag-5'>生命周期</b>

    編譯器的標(biāo)準(zhǔn)生命周期

    編譯器的標(biāo)準(zhǔn)生命周期
    發(fā)表于 07-05 19:32 ?1次下載
    編譯器的標(biāo)準(zhǔn)<b class='flag-5'>生命周期</b>

    鴻蒙開發(fā):【PageAbility的生命周期

    PageAbility生命周期是PageAbility被調(diào)度到INACTIVE、ACTIVE、BACKGROUND等各個狀態(tài)的統(tǒng)稱。PageAbility生命周期流轉(zhuǎn)及狀態(tài)說明見如下圖1、表1所示。
    的頭像 發(fā)表于 06-17 10:05 ?917次閱讀
    鴻蒙開發(fā):【PageAbility的<b class='flag-5'>生命周期</b>】

    鴻蒙開發(fā)組件:DataAbility的生命周期

    應(yīng)用開發(fā)者可以根據(jù)業(yè)務(wù)場景實現(xiàn)data.js/data.ets生命周期相關(guān)接口。DataAbility生命周期接口說明見下表。
    的頭像 發(fā)表于 06-20 09:39 ?657次閱讀