OverView
Java程序員都應清楚Spring生命週期,這是Java程序員的基礎知識。緊緊掌握這些知識點這不單單能夠應付面試,更重要的是,能夠更好的分析實際工做中的問題。
本文將把SpringBoot、Spring、Dubbo結合起來,分析他們的啓動流程。整個過程大體會長下面這個樣子。
下面,咱們就分別看看SpringBoot
的啓動過程。程序員
SpringBoot的啓動過程
SpringBoot
能夠理解爲Spring的啓動程序,啓動程序的入口方法爲SpringApplication.run()
,詳細以下:
面試
A: 通知 Listener,start
B: 建立Enviroment
,Enviroment
是整個應用的配置以及Profile
的承載類
C: 建立容器
D: 初始化容器, ApplicationContext.refresh()
即爲容器初始化入口
E: 空方法
F: 通知 Listener,started
G: 通知 Listener,running
經過觀察發現:SpringBoot.run()
中代碼步驟,大體能夠概括總結爲兩種行爲動做:app
SpringApplicationRunListeners
調用(藍色)- 建立和初始化容器(綠色)兩部分
因此我的以爲SpringApplicationRunListeners
表明了SpringBoot
的生命週期,這個生命週期描述了SpringBoot的啓動過程,如:建立初始化Enviroment
,建立初始化容器
總結:SpringBoot的生命週期,以下圖:post
Spring啓動過程
在SpringBoot啓動過程當中,會建立、刷新ApplicationContext
。結合上面的流程後,以下圖:
這裏的refreshContext
,就是Spring容器建立初始化的過程,下面咱們詳細介紹一下此過程。spa
Spring中有一個類AbstractApplicationContext
,全部類型的ApplicationContext,例如ClassPathXmlApplicationContext
,FileSystemXmlApplicationContext
AnnotationConfigApplicationContext
都是繼承此類。
AbstractApplicationContext 中有一個著名的方法refresh(),Spring容器的設計者們將容器啓動過程抽象到了這個方法中,也就是AbstractApplication.refresh()
方法中。 全部類型的ApplicationContext都會進入此方法。
debug
Dubbo的啓動過程
Dubbo程序是以Spring Beans的形式存在於Spring容器中,隨着Spring容器啓動而啓動。
對於Dubbo業務方來講,主要有兩個重要的Bean,ServiceBean
和ReferenceBean
,他們各自會調用Service.export()和Reference.get()來暴露服務以及引用遠程服務。
在使用這兩個Bean的時候,Dubbo的設計者爲了讓用戶能夠以Annotation的方式方便的使用,他們利用Spring的衆多擴展點,在Spring容器啓動過程當中,自動發現、註冊、實例化了ServiceBean
與ReferenceBean
。設計
具體流程圖以下:
3d
BeanDefinition的註冊
EnableDubbo:
若是咱們是使用Annotation方式使用Dubbo,那麼會在SpringConfig類中添加@EnableDubbo
註解,這個註解會利用@Import
註解的BeanDefinition註冊機制,向容器中註冊DubboConfigBindingBeanPostProcessor
ServiceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcesser
這三個重要的postProcessor來完成ServiceBean
與ReferenceBean
的建立。代理
@Import註解是由下面的ConfigurationClassPostProcessor
讀取執行的。code
ConfigurationClassPostProcessor:
Spring在容器的refresh()方法執行過程當中,當BeanFactory準備好後就會執行invokeBeanFactoryPostProcessors(BeanFactory)
,若是debug源碼會發現剛開始候容器只有ConfigurationClassPostProcessor
這一個BeanFactoryPostProcessor,它的做用,按照源碼的說法是:Bootstrapping processing of @Configuration 。源碼註解大概意思是:它是第一個加載進容器並被執行的BeanFactoryPostProcessor
,而後他做爲Configuration引導過程,自動導入程序中的其餘Configuration相關類。
原來,@Configuration @Import就是由它讀取執行的。
ServiceAnnotationBeanPostProcessor:
時機:
ServiceAnnotationBeanPostProcessor
是一個BeanFactoryPostProcessor在容器invokeBeanFactoryPostProcessors()過程當中,會被執行。
做用:以@Service
做爲過濾條件,掃描指定scanBasePackages
,向容器註冊ServiceBean。在refresh完成的時候,會向容器中發送ContextRefershEvent
,ServiceBean實例會監聽此事件,而後執行服務export過程。
擴展點:BeanFactoryPostProcessor
Bean初始化
ReferenceAnnotationBeanPostProcessor:
時機:
- 在容器初始化完成後,會實例化容器中的單例非懶初始化Bean。
- 在實例化Bean之後,初始化Bean屬性前會調用populateBean()方法,執行
AnnotationInjectedBeanPostProcessor
爲注入依賴的屬性。 - 而
ReferenceAnnotationBeanPostProcessor
就是繼承自AnnotationInjectedBeanPostProcessor
,此時它會隨着一塊兒執行。
動做:
- 加載掃描目錄
scanBasePackages
下的類,找到@Reference
所註解的字段,爲其注入值。 - 注入的值爲業務接口的動態代理類,動態代理(InvocationHandler)的邏輯是調用
ReferenceBean.get()
方法,建立真正的Invoker
。 - 因此最終注入了封裝了遠程調用邏輯的
Invoker
Sping擴展點:BeanPostProcessor
AnnotationInjectedBeanPostProcessor
DubboConfigBindingBeanPostProcessor:
做用:爲配置承載類:ApplicationConfig
ModuleConfig
RegistryConfig
ProtocolConfig
等自動狀態配置
Spring擴展點:BeanPostProcessor