前言
BeanFactory
是
spring boot
的最重要的核心元件,當然也是
spring boot
非常基礎的元件,是以梳理清楚
BeanFactory
的源碼才是梳理清楚
Spring boot
源碼的關鍵。前天,我們分享了
beanDefinitionNames
和
beanDefinitionMap
的初始化過程,雖然過程中有涉及到
beanFactory
的相關知識點,但是關于
beanFactroy
我們還沒有正式地分析過它,關于它的初始化過程,也是一無所知,為了更系統地了解
beanFactory
,從今天開始我們開始更系統地分析
beanFactory
的相關源碼,下面我們就先來看下
BeanFactory
的初始化過程。
BeanFactory初始化
今天我們依然是從一張時序圖開始講起,下面這張時序圖就是
spring boot
容器的
BeanFactory
初始化過程,
beanFactory
初始化其實是和容器的初始化同時完成的,它也是容器初始化過程中的重要一步:
在上面的時序圖中,最關鍵的内容就是
AnnotationConfigServletWebServerApplicationContext
的執行個體化過程,這裡面涉及到
java
類的初始化流程:建立子類時,必須先調用父類無參構造方法,是以
AnnotationConfigServletWebServerApplicationContext
是在所有父類執行個體化完成後,才完成它自己的執行個體化過程的。下面我們就來看
AnnotationConfigServletWebServerApplicationContext
的初始化流程。
createApplicationContext
在
debug
的過程中,我發現
BeanFactory
在容器被建立後就已經被初始化,這也就是說
BeanFactory
其實是在
spring boot
容器建立過程中被初始化的,是以我們今天主要就是研究容器建立過程,也就是
createApplicationContext()
方法:
關于
createApplicationContext
這個方法,我們前面已經展示過了,它的作用就是通過反射建立容器執行個體:
AnnotationConfigServletWebServerApplicationContext執行個體化
通過跟蹤代碼,最終可以确認,調用的是
AnnotationConfigServletWebServerApplicationContext
無參構造方法:
是以下面就是對
AnnotationConfigServletWebServerApplicationContext
的執行個體化,由于容器這塊繼承關系比較複雜,是以執行個體化順序也比較複雜。
容器執行個體化
雖然各位小夥伴可能很清楚
java
對象執行個體化過程,但是我覺得還是有必要再補充說明下。在有繼承關系的
java
對象執行個體化過程中,如果目前類繼承了父類,在執行個體化目前類時,先要調用父類的無參構造方法(就算不指定,也會隐式調用)。是以,在這裡初始
AnnotationConfigServletWebServerApplicationContext
時,會先調用它的父類無參構造方法,下面是
AnnotationConfigServletWebServerApplicationContext
的繼承關系,看起來确實很複雜:
在跟蹤代碼的過程中,最終我确認
BeanFactory
是在
GenericApplicationContext
的無參構造方法中完成初始化的,也就是
AnnotationConfigServletWebServerApplicationContext
父類的父類的父類:
是以初始化的過程就是,
AnnotationConfigServletWebServerApplicationContext
的無參構造方法中先調用
ServletWebServerApplicationContext
的無參構造方法,
ServletWebServerApplicationContext
GenericWebApplicationContext
GenericWebApplicationContext
的無參構造方法先調用
GenericApplicationContext
的無參構造方法(無限套娃)……
知識擴充
後續的調用這裡就直接省略了,因為他們和
BeanFactory
沒有關系,而且因為繼承關系過于複雜,是以這裡我們要盡可能簡單。在這裡所有的初始化操作中,調用父類構造方法始終是首先被執行的,也必須首先被執行(首先調用父類的無參構造方法),這也就是為什麼我們在寫類的有參構造方法的時候,如果父類沒有無參構造方法時,必須顯式調用父類有參構造方法,且必須放在第一行的原因: