首先我提出一個問題:一個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
!緩存
BeanDefinition
裏面描述了不少的東西,大體以下:markdown
他裏面存放了Spring建立bean的過程當中所須要的一切原料!post
經過上面的介紹,那麼你對
BeanDefinition
有了一大概的認識,那麼咱們在瞭解整個Spring的聲明週期的時候,須要瞭解兩個概念BeanFactoryPostProcessor
、BeanPostProcessor
,固然這裏只是普及一下概念,是爲了可以讓讀者更加深刻的去理解Spring的聲明週期!學習
咱們如今經過上面的瞭解知道了一件事,就是Spring在建立對象以前會把class轉換成一個BeanDefinition
, 此時Spring爲咱們提供了一個擴展點,他能夠在讀取徹底部的class轉換爲 BeanDefinition
以後,回調全部實現了BeanFactoryPostProcessor
接口的實現類,並傳入工廠對象,使得使用者可以對工廠對象內部的屬性進行修改,例如:對BeanDefinition
內的信息進行修改,以達到操縱最終實例化bean的目的!spa
說白了,他會在掃描完項目將Class轉換爲BeanDefinition
以後在進行實例化以前進行接口的回調!code
這個類和上面那個類十分的類似,他有兩個方法,兩個方法的調用時機也不相同,他會在實例化以後,調用初始化方法以前進行第一次方法回調(postProcessBeforeInitialization),在執行完初始化方法以後又會進行一次回調(postProcessAfterInitialization),每次回調該類都會將當前建立好的bean傳遞到方法內部,從而讓開發者可以自定義的修改當前bean的一些定義!orm
那麼此時,咱們瞭解了BeanDefinition
、BeanPostProcessor
、BeanFactoryPostProcessor
這三個概念以後,咱們能夠嘗試着學習一下Spring的生命週期,學習Spring聲明週期對掌握Spring源碼具備舉足輕重的地位!只有瞭解Spring的聲明週期,纔可以對後續Spring系列的技術進行一個詳盡的源碼掌握!
整個Spring的生命週期,以文字描述大概分爲如下幾個階段:
BeanFactoryPostProcessor
掃描項目將全部的@Bean、@Component....
或者xml配置
等符合Spring讀取對着的類解析成 BeanDefinition
,存儲在容器裏面!BeanFactoryPostProcessor
BeanPostProcessor
到容器內部!BeanPostProcessors.postProcessBeforeInitialization
方法BeanPostProcessors.postProcessAfterInitialization
方法儘管咱們能夠經過實現BeanDefinition
接口建立一個自定義的BeanDefinition
,可是你是否發現,本身實現這個接口,想要建立一個BeanDefinition
極其複雜裏面幾十個屬性都須要你本身去設置;
Spring官方爲了簡化這一步驟,提供了一個抽象AbstractBeanDefinition
,這個抽象類內部默認實現了BeanDefinition
的絕大部分方法,對一些屬性進行了默認值的賦值,極大地簡化了用戶本身實現一個BeanDefinition
的難度!
他是AbstractBeanDefinition
的子類,咱們經過註解配置的bean以及咱們的配置類(除@Bean
)外的BeanDefiniton
類型都是GenericBeanDefinition
類型的!
Spring在啓動時會實例化幾個初始化的BeanDefinition
,這幾個BeanDefinition
的類型都爲RootBeanDefinition
,這個包括後續Spring的BeanDefinition會進行一個合併(這都是後話)都是RootBeanDefinition
類型的!
咱們經過 @Bean
建立的BeanDefinition
也是RootBeanDefinition類型,固然是屬於他的子類(後面會介紹)的!
這個接口直接繼承了BeanDefinition
,他在原來的基礎上擴展了兩個方法:
這兩個方法是專門對註解讀取的方法!全部註解標識的bean都是這個類型的bean!
第一種狀況是配置類也就是標註了@Configuration
註解的類會被解析成 AnnotatedGenericBeanDefinition
第二種狀況是經過@Import
導入的類會被解析成AnnotatedGenericBeanDefinition
經過@Bean
註解導入的類會被解析爲ConfigurationClassBeanDefinition
經過@Service、@Compent
等方式建立的bean 會以ScannedGenericBeanDefinition
的形式存在!
才疏學淺,若是文章中理解有誤,歡迎大佬們私聊指正!歡迎關注做者的公衆號,一塊兒進步,一塊兒學習!