日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

如果你每次面试前都要去背一篇Spring中Bean的生命周期,请看完这篇文章

發布時間:2025/3/16 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如果你每次面试前都要去背一篇Spring中Bean的生命周期,请看完这篇文章 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

當你準備去復習Spring中Bean的生命周期的時候,這個時候你開始上網找資料,很大概率會看到下面這張圖:

先不論這張圖上是否全面,但是就說這張圖吧,你是不是背了又忘,忘了又背?

究其原因在于,你沒有理解為什么需要這些步驟,也不知道為什么要按這個順序執行

筆者在閱讀完整個IOC跟AOP的源碼后,希望通過這篇文章講一講我的Spring中Bean生命周期的看法,幫助大家能理解性的記憶整個流程,而不是死記硬背!


基礎知識補充

所謂理解也是建立在有一定知識儲備的基礎上的,所以這里先補充一些基礎概念

Bean創建的三個階段

Spring在創建一個Bean時是分為三個步驟的

  • 實例化,可以理解為new一個對象

  • 屬性注入,可以理解為調用setter方法完成屬性注入

  • 初始化,你可以按照Spring的規則配置一些初始化的方法(例如,@PostConstruct注解)

生命周期的概念

Bean的生命周期指的就是在上面三個步驟中后置處理器BeanPostprocessor穿插執行的過程

后置處理器的分析

按照實現接口進行分類

  • 直接實現了BeanPostProcessor接口

  • 最簡單的后置處理器,也就是說直接實現了BeanPostProcessor接口,這種后置處理器只能在初始化前后執行

    public?interface?BeanPostProcessor?{//?初始化前執行的方法@Nullabledefault?Object?postProcessBeforeInitialization(Object?bean,?String?beanName)?throws?BeansException?{return?bean;}????//?初始化后執行的方法default?Object?postProcessAfterInitialization(Object?bean,?String?beanName)?throws?BeansException?{return?bean;}}
  • 直接實現了InstantiationAwareBeanPostProcessor接口

  • 在第一種后置處理的基礎上進行了一層擴展,可以在Bean的實例化階段前后執行

    //?繼承了BeanPostProcessor,額外提供了兩個方法用于在實例化前后的階段執行 //?因為實例化后緊接著就要進行屬性注入,所以這個接口中還提供了一個屬性注入的方法 public?interface?InstantiationAwareBeanPostProcessor?extends?BeanPostProcessor?{//?實例化前執行default?Object?postProcessBeforeInstantiation(Class<?>?beanClass,?String?beanName)?throws?BeansException?{return?null;}//?實例化后置default?boolean?postProcessAfterInstantiation(Object?bean,?String?beanName)?throws?BeansException?{return?true;}//?屬性注入default?PropertyValues?postProcessPropertyValues(PropertyValues?pvs,?PropertyDescriptor[]?pds,?Object?bean,?String?beanName)?throws?BeansException?{return?pvs;} }
  • Spring內部專用的后置處理器

  • 可能有的小伙伴認為,第三種后置處理器肯定就是用來在屬性注入前后執行了的吧。我只能說,大兄弟,太天真了,看看下面這張圖

    這種情況下再為屬性注入階段專門提供兩個方法是不是有點多余呢?實際上第三種后置處理器是Spring為了自己使用而專門設計的

    public?interface?SmartInstantiationAwareBeanPostProcessor?extends?InstantiationAwareBeanPostProcessor?{//?推測bean的類型,例如在屬性注入階段我們就需要知道符合依賴類型的Bean有哪些@Nullabledefault?Class<?>?predictBeanType(Class<?>?beanClass,?String?beanName)?throws?BeansException?{return?null;}//?推斷出所有符合要求的構造函數,在實例化對象的時候我們就需要明確到底使用哪個構造函數@Nullabledefault?Constructor<?>[]?determineCandidateConstructors(Class<?>?beanClass,?String?beanName)throws?BeansException?{return?null;}//?獲取一個提前暴露的對象,用于解決循環依賴default?Object?getEarlyBeanReference(Object?bean,?String?beanName)?throws?BeansException?{return?bean;}}

    一般我們在探究生命周期的時候都不會考慮這種后置處理器的執行


    生命周期詳細介紹

    在了解了上面的概念后,我們再來看看這張圖

    至少現在這張圖上缺少了實例化前后后置處理器的執行流程,對吧?

    再補充上這一點之后,我們再來看看,屬性注入后緊接著已經是初始化的階段,在初始化階段開始前應該要調用BeanPostProcessor的預初始化方法(postProcessBeforeInitialization),然后調用自定義的初始化方法,最后調用postProcessAfterInitialization

    這是沒有問題,但是為什么要在初始前還要調用Aware接口的方法,如果你看了源碼的話可能會說,源碼就是這么寫的,別人就是這么設計的,但是為什么要這么設計呢?我們看源碼到一定階段后不應該僅僅停留在是什么的階段,而應該多思考為什么,這樣能幫助你更好的了解這個框架

    那么為什么Aware接口非要在初始化前執行呢?

    這樣做的目的是因為,初始化可能會依賴Aware接口提供的狀態,例如下面這個例子

    @Component public?class?A?implements?InitializingBean,?ApplicationContextAware?{ApplicationContext?applicationContext;@Overridepublic?void?afterPropertiesSet()?throws?Exception?{//?初始化方法需要用到ApplicationContextAware提供的ApplicationContextSystem.out.println(applicationContext);}@Overridepublic?void?setApplicationContext(ApplicationContext?applicationContext)?throws?BeansException?{this.applicationContext?=?applicationContext;} }

    這種情況下Aware接口當然要在初始化前執行啦!

    另外,在討論Bean的初始化的時候經常會碰到下面這個問題,@PostConstruct,afterPropertiesSet跟XML中配置的init-method方法的執行順序。

    請注意,@PostConstruct實際上是在postProcessBeforeInitialization方法中處理的,嚴格來說它不屬于初始化階段調用的方法,所以這個方法是最先調用的

    其次我們思考下是調用afterPropertiesSet方法的開銷大還是執行配置文件中指定名稱的初始化方法開銷大呢?我們不妨用偽代碼演示下

    // afterPropertiesSet,強轉后直接調用 ((InitializingBean)?bean).afterPropertiesSet()//?反射調用init-method方法 //?第一步:找到這個方法 Method?method?=?class.getMethod(methodName) //?第二步:反射調用這個方法 method.invoke(bean,null)

    相比而言肯定是第一種的效率高于第二種,一個只是做了一次方法調用,而另外一個要調用兩次反射。

    因此,afterPropertiesSet的優先級高于XML配置的方式

    所以,這三個方法的執行順序為:

  • @PostConstruct注解標注的方法

  • 實現了InitializingBean接口后復寫的afterPropertiesSet方法

  • XML中自定義的初始化方法

  • 在完成初始化,沒什么好說的了,最后調用一下postProcessAfterInitialization,整個Bean的生命周期到此結束

    ??

    總結

    本文的主要目的是想要幫助大家更好的理解整個Bean的生命周期,不過理解是建立在有一定知識存儲的基礎上的

    你至少要對Bean的后置處理器跟Bean創建有一個大概的理解,那么通過本文你能理清一些細節方面的東西

    例如,為什么Aware接口執行在初始化階段之前?為什么初始化的三個方法會按

    @PostConstruct,afterPropertiesSet,XML中定義的初始化方法這個順序執行。

    有道無術,術可成;有術無道,止于術

    歡迎大家關注Java之道公眾號

    好文章,我在看??

    總結

    以上是生活随笔為你收集整理的如果你每次面试前都要去背一篇Spring中Bean的生命周期,请看完这篇文章的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。