想要學會Spring源碼,你必知必會的BeanDefinition原理!

1、BeanDefinition淺析

1. 基本概念瞭解

首先我提出一個問題:一個java對象和一個Spring Bean有什麼區別?java

這是一個經典的面試題,什麼是java Object?萬物皆對象,在Java內部全部的類,通過建立以後均可以稱之爲一個對象,SpringBean也是一個java Object, 可是Spring Bean是脫離於JAVA Object的,爲何這麼說呢?由於一個class要想變成對象只須要new一下,就可以稱之爲一個對象,可是一個類要想變成一個Spring Bean就須要通過一系列的生命週期,什麼生命週期呢?後面會說到!面試

至少從上面的能夠知道,Spring Bean是一個特殊的Java Object, 那麼他確定有和JAVA Object有不同的地方!spring

Java中 Class對象能夠描述一個JAVA Object,可是由於Spring Bean是一個特殊的JAVA Object,因此Class對象不可以完整的描述一個Spring Bean,因此Spring官方單獨開發了一個叫作BeanDefinition的類,來描述一個SpringBean緩存

2. 大體結構

BeanDefinition裏面描述了不少的東西,大體以下:markdown

image-20200907164143213

他裏面存放了Spring建立bean的過程當中所須要的一切原料!post

3. 他是幹嗎的(Spring構建它的優點)?

  • 提高效率: Spring建立一個類是經過反射建立的,建立類的時候須要一些建立信息,好比Class,好比註解信息等等,實事先將這些信息緩存起來,在建立bean的時候可以直接從緩存中獲取從而達到提高建立效率的目的。
  • 方便修改:spring建立對象的時候,建立的信息所有是經過 BeanDefinition 內存儲的信息來建立對象的,因此,咱們能夠經過修改BeanDefinition內部特定的值來改變Spring建立對象的結果!
  • 方便擴展:咱們經過一些特定的接口,能夠獲取到一個類的全部的BeanDefinition信息,從而完成一些特定功能的實現!

2、Spring生命週期

經過上面的介紹,那麼你對BeanDefinition有了一大概的認識,那麼咱們在瞭解整個Spring的聲明週期的時候,須要瞭解兩個概念BeanFactoryPostProcessorBeanPostProcessor,固然這裏只是普及一下概念,是爲了可以讓讀者更加深刻的去理解Spring的聲明週期!學習

1. 什麼是BeanFactoryPostProcessor?

咱們如今經過上面的瞭解知道了一件事,就是Spring在建立對象以前會把class轉換成一個BeanDefinition , 此時Spring爲咱們提供了一個擴展點,他能夠在讀取徹底部的class轉換爲 BeanDefinition 以後,回調全部實現了BeanFactoryPostProcessor 接口的實現類,並傳入工廠對象,使得使用者可以對工廠對象內部的屬性進行修改,例如:對BeanDefinition內的信息進行修改,以達到操縱最終實例化bean的目的!spa

說白了,他會在掃描完項目將Class轉換爲BeanDefinition 以後在進行實例化以前進行接口的回調!code

2. 什麼是BeanPostProcessor?

這個類和上面那個類十分的類似,他有兩個方法,兩個方法的調用時機也不相同,他會在實例化以後,調用初始化方法以前進行第一次方法回調(postProcessBeforeInitialization),在執行完初始化方法以後又會進行一次回調(postProcessAfterInitialization),每次回調該類都會將當前建立好的bean傳遞到方法內部,從而讓開發者可以自定義的修改當前bean的一些定義!orm

3. Spring生命週期淺析

那麼此時,咱們瞭解了BeanDefinitionBeanPostProcessorBeanFactoryPostProcessor這三個概念以後,咱們能夠嘗試着學習一下Spring的生命週期,學習Spring聲明週期對掌握Spring源碼具備舉足輕重的地位!只有瞭解Spring的聲明週期,纔可以對後續Spring系列的技術進行一個詳盡的源碼掌握!

整個Spring的生命週期,以文字描述大概分爲如下幾個階段:

  1. 初始化bean容器,以方便後續的全部的讀取的信息的存儲!
  2. 初始化內置的class文件轉換爲bd
  3. 初始化bean工廠,設置一些默認值!
  4. 向BeanFactory內部註冊一些本身自己內置的Bean後置處理器
  5. 執行項目內置的BeanFactoryPostProcessor掃描項目將全部的@Bean、@Component....或者xml配置等符合Spring讀取對着的類解析成 BeanDefinition,存儲在容器裏面!
  6. 執行咱們自定義的 BeanFactoryPostProcessor
  7. 註冊全部的BeanPostProcessor到容器內部!
  8. 初始化國際化資源
  9. 初始化事件資源
  10. 實例化class
  11. 按照規則進行屬性填充(自動注入)
  12. 回調BeanPostProcessors.postProcessBeforeInitialization方法
  13. 調用bean的初始化方法
  14. 回調BeanPostProcessors.postProcessAfterInitialization方法

123

3、BeanDefinition詳解

1. AbstractBeanDefinition

儘管咱們能夠經過實現BeanDefinition接口建立一個自定義的BeanDefinition,可是你是否發現,本身實現這個接口,想要建立一個BeanDefinition極其複雜裏面幾十個屬性都須要你本身去設置;

Spring官方爲了簡化這一步驟,提供了一個抽象AbstractBeanDefinition,這個抽象類內部默認實現了BeanDefinition的絕大部分方法,對一些屬性進行了默認值的賦值,極大地簡化了用戶本身實現一個BeanDefinition的難度!

I. GenericBeanDefinition

他是AbstractBeanDefinition的子類,咱們經過註解配置的bean以及咱們的配置類(除@Bean)外的BeanDefiniton類型都是GenericBeanDefinition類型的!

II. RootBeanDefinition

Spring在啓動時會實例化幾個初始化的BeanDefinition,這幾個BeanDefinition的類型都爲RootBeanDefinition,這個包括後續Spring的BeanDefinition會進行一個合併(這都是後話)都是RootBeanDefinition類型的!

咱們經過 @Bean建立的BeanDefinition也是RootBeanDefinition類型,固然是屬於他的子類(後面會介紹)的!

2. AnnotatedBeanDefinition

這個接口直接繼承了BeanDefinition,他在原來的基礎上擴展了兩個方法:

image-20200907180423084

這兩個方法是專門對註解讀取的方法!全部註解標識的bean都是這個類型的bean!

I. AnnotatedGenericBeanDefinition

image-20200907180954450

第一種狀況是配置類也就是標註了@Configuration註解的類會被解析成 AnnotatedGenericBeanDefinition

第二種狀況是經過@Import導入的類會被解析成AnnotatedGenericBeanDefinition

II. ConfigurationClassBeanDefinition

image-20200907182021917

經過@Bean註解導入的類會被解析爲ConfigurationClassBeanDefinition

III. ScannedGenericBeanDefinition

image-20200907182139696

經過@Service、@Compent等方式建立的bean 會以ScannedGenericBeanDefinition的形式存在!

才疏學淺,若是文章中理解有誤,歡迎大佬們私聊指正!歡迎關注做者的公衆號,一塊兒進步,一塊兒學習! 歡迎關注做者

相關文章
相關標籤/搜索