圖解:SpringBoot Spring Dubbo 啟動過程


OverView

Java程序員都應清楚Spring生命周期,這是Java程序員的基礎知識。牢牢掌握這些知識點這不僅僅可以應付面試,更重要的是,可以更好的分析實際工作中的問題。
本文將把SpringBoot、Spring、Dubbo結合起來,分析他們的啟動流程。整個過程大致會長下面這個樣子。
屏幕快照 2020-01-01 下午10.26.07
下面,我們就分別看看SpringBoot的啟動過程。

SpringBoot的啟動過程

SpringBoot可以理解為Spring的啟動程序,啟動程序的入口方法為SpringApplication.run(),詳細如下:

A: 通知 Listener,start
B: 創建EnviromentEnviroment是整個應用的配置以及Profile的承載類
C: 創建容器
D: 初始化容器, ApplicationContext.refresh()即為容器初始化入口
E: 空方法
F: 通知 Listener,started
G: 通知 Listener,running
通過觀察發現:SpringBoot.run()中代碼步驟,大致可以歸納總結為兩種行為動作:

  • SpringApplicationRunListeners調用(藍色)
  • 創建和初始化容器(綠色)兩部分
    所以個人覺得SpringApplicationRunListeners代表了SpringBoot的生命周期,這個生命周期描述了SpringBoot的啟動過程,如:創建初始化Enviroment,創建初始化容器

總結:SpringBoot的生命周期,如下圖:

Spring啟動過程

在SpringBoot啟動過程中,會創建、刷新ApplicationContext。結合上面的流程后,如下圖:

這里的refreshContext,就是Spring容器創建初始化的過程,下面我們詳細介紹一下此過程。

Spring中有一個類AbstractApplicationContext,所有類型的ApplicationContext,例如ClassPathXmlApplicationContextFileSystemXmlApplicationContext AnnotationConfigApplicationContext 都是繼承此類。
AbstractApplicationContext 中有一個著名的方法refresh(),Spring容器的設計者們將容器啟動過程抽象到了這個方法中,也就是AbstractApplication.refresh()方法中。 所有類型的ApplicationContext都會進入此方法。

Dubbo的啟動過程

Dubbo程序是以Spring Beans的形式存在於Spring容器中,隨着Spring容器啟動而啟動。
對於Dubbo業務方來說,主要有兩個重要的Bean,ServiceBeanReferenceBean,他們各自會調用Service.export()Reference.get()來暴露服務以及引用遠程服務。
在使用這兩個Bean的時候,Dubbo的設計者為了讓用戶可以以Annotation的方式方便的使用,他們利用Spring的眾多擴展點,在Spring容器啟動過程中,自動發現、注冊、實例化了ServiceBeanReferenceBean

具體流程圖如下:

BeanDefinition的注冊

EnableDubbo
如果我們是使用Annotation方式使用Dubbo,那么會在SpringConfig類中添加@EnableDubbo注解,這個注解會利用@Import注解的BeanDefinition注冊機制,向容器中注冊DubboConfigBindingBeanPostProcessor ServiceAnnotationBeanPostProcessor ReferenceAnnotationBeanPostProcesser這三個重要的postProcessor來完成ServiceBeanReferenceBean的創建。

@Import注解是由下面的ConfigurationClassPostProcessor讀取執行的。

ConfigurationClassPostProcessor
Spring在容器的refresh()方法執行過程中,當BeanFactory准備好后就會執行invokeBeanFactoryPostProcessors(BeanFactory),如果debug源碼會發現剛開始候容器只有ConfigurationClassPostProcessor 這一個BeanFactoryPostProcessor,它的作用,按照源碼的說法是:Bootstrapping processing of @Configuration 。源碼注解大概意思是:它是第一個加載進容器並被執行的BeanFactoryPostProcessor,然后他作為Configuration引導過程,自動導入程序中的其他Configuration相關類。
原來,@Configuration @Import就是由它讀取執行的。

ServiceAnnotationBeanPostProcessor
時機:

  1. ServiceAnnotationBeanPostProcessor是一個BeanFactoryPostProcessor在容器invokeBeanFactoryPostProcessors()過程中,會被執行。

作用:以@Service作為過濾條件,掃描指定scanBasePackages,向容器注冊ServiceBean。在refresh完成的時候,會向容器中發送ContextRefershEvent,ServiceBean實例會監聽此事件,然后執行服務export過程。

擴展點:BeanFactoryPostProcessor

Bean初始化

ReferenceAnnotationBeanPostProcessor
時機:

  1. 在容器初始化完成后,會實例化容器中的單例非懶初始化Bean。
  2. 在實例化Bean以后,初始化Bean屬性前會調用populateBean()方法,執行AnnotationInjectedBeanPostProcessor為注入依賴的屬性。
  3. ReferenceAnnotationBeanPostProcessor就是繼承自AnnotationInjectedBeanPostProcessor,此時它會隨着一起執行。

動作:

  1. 加載掃描目錄scanBasePackages下的類,找到@Reference所注解的字段,為其注入值。
  2. 注入的值為業務接口的動態代理類,動態代理(InvocationHandler)的邏輯是調用ReferenceBean.get()方法,創建真正的Invoker
  3. 所以最終注入了封裝了遠程調用邏輯的Invoker

Sping擴展點:BeanPostProcessor AnnotationInjectedBeanPostProcessor

DubboConfigBindingBeanPostProcessor
作用:為配置承載類:ApplicationConfigModuleConfig RegistryConfig ProtocolConfig等自動狀態配置
Spring擴展點:BeanPostProcessor


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM