SpringBoot啓動分析

一般咱們都是在main方法中調用SpringApplication.run()方法啓動SpringBoot應用的,web

今天來看一下啓動過程當中都幹了些什麼。上圖。spring

wKiom1nZgFzidkJ9AADZ1ECFUm0224.png

wKioL1nZgA2icE8MAABtw0yNx-c157.png

wKiom1nZgF2wm0VCAACCYRdplLY602.png

wKioL1nZgA7zw5ENAAAgKuEJD00040.png

大體分爲兩步,第一步new一個SpringApplication對象,第二步調用其run方法。ide

在建立SpringApplication對象的時候作了如下幾件事情:ui

(1)判斷應用是否是Web應用,判斷的依據是classpath中有沒有Servlet和ConfigurableWebApplicationContext,具體來說就是,能不能成功獲取到它們的Class對象spa

(2)設置Initializer和Listener3d

(3)判斷main方法對象

這裏有必要了解一下ApplicationContextInitializer和ApplicationListener是幹什麼的blog

wKiom1nZgyjwBfIiAAEjexBMnC8727.png

首先,ApplicationContextInitializer它是初始化Spring ConfigurableApplicationContext的時候的回調接口,它會先於ConfigurableApplicationContext的refresh()方法被調用。而咱們知道ConfigurableApplicationContext的refresh()方法是在AbstractApplicationContext中實現的。接口

wKioL1nZh_XBeYx6AACs5LS3odA910.png

ApplicationListener是一個基於標準的EventListener的事件監聽器,用的是觀察者模式。事件

這兩步都有一個共同點就是都調用getSpringFactoriesInstances()方法,下面看下:

wKiom1nZiZHAyZ65AACFiKeXUzw475.png

wKioL1nZiULSIN5fAAEHKx47UZw843.png

wKioL1nZiUKw-G5-AAApJ-2OdxY502.png

它的做用就是從classpath中全部的META-INF/spring.factories文件中找到指定Key的值。(注意:是全部的META-INF/spring.factories

而後將其以List形式返回,並實例化它們。

在咱們的例子中,這兩次找的key值分別是:org.springframework.context.ApplicationContextInitializer和org.springframework.context.ApplicationListener

咱們具體看一下它們的值是什麼

wKioL1nZiqrCIFmKAACIpN4gLo4351.png

wKiom1nZivqQMSN9AADNjNTdV3A006.png


總之呢,咱們能夠知道在容器啓動的過程當中,ApplicationContextInitializer的initialize()方法在AbstractApplicationContext的refresh()方法以前被調用。

到此爲止,SpringApplication對象已經建立好了,接下來調用其run()方法。


這裏先來了解一下SpringApplicationRunListener,它是SpringApplication#run()方法的一個監聽器,並無什麼實質性的做用。

wKiom1nZnNLj1CZ0AACiEsZjBiE065.pngwKioL1nZnOOhdHZaAAAZT1QVDZ8656.png接下來在看run方法的時候,咱們將忽略SpringApplicationRunListener這個監聽器。

wKioL1nZneKQCAk-AAD7uxi43BQ489.png


第1步、建立一個ApplicationArguments對象,它是對咱們運行時傳進來的參數的一個封裝

第2步、建立並配置Environment。這裏,若是是web環境,則建立StandardServletEnvironment,不然建立一個StandardEnvironment

wKiom1nZoC6CHU5QAAAsrSU5bKA587.png

wKiom1nZsvuic9pmAAA4YBgkOlU677.png

第3步、打印Banner

第4步、初始化ApplicationContext。這裏,若是是web環境,則實例化AnnotationConfigEmbeddedWebApplicationContext,不然實例化AnnotationConfigApplicationContext。

wKioL1nZoSWzZzOtAACeUjOpJl8745.png

wKiom1nZoXSyA_4qAABnNvW1UG4956.png

第5步、建立FailureAnalyzers對象

第6步、準備上下文

(1)若是BeanNameGenerator不爲空,將其註冊到BeanFactory。(PS:其實就是ApplicationContext)

(2)調用全部ApplicationContextInitializer的initialize()方法

(3)將ApplicationArguments和Banner的實例註冊到Context

(4)加載Sources

wKioL1nZpMeTiUFAAAC1ezz2RHI959.png

wKiom1nZpRbTagulAACd5KPPD0o329.png

wKioL1nZpMfBbGHeAACrp2K3YEM870.png


到這裏,sources中全部的Bean都被加載到Context中了

第7步、刷新Context。這裏它直接調用的AbstractApplicationContext的refresh()方法,前面的文章已經介紹過了,這裏再也不贅述。

wKioL1nZpdDTOC3HAAA-PXfvQjE895.png

wKiom1nZpiDQyWCtAACy0WqRd7E939.png


第8步、調用Context中全部的ApplicationRunner和CommandLineRunner

wKioL1nZpsvj05_cAACcNlLHtrE549.png

到此爲止,啓動完成!!!

總結:

第1步、全部的源對象(source)保存到Set<Object> sources成員變量中

第2步、判斷是否web環境

第3步、設置Initializer和Listener

第4步、判斷main方法

第5步、建立ApplicationArguments對象

第6步、建立並配置環境

第7步、建立Banner

第8步、建立ApplicationContext

第9步、配置ApplicationContext。在這一步中會回調全部的ApplicationContextInitializer,還會註冊一些特殊的Bean到Context,最重要的是會加載sources中所配置的全部的Bean到Context中。

第10步、刷新Context。這裏直接調用AbstractApplicationContext的refresh()方法。

第11步、調用容器中全部的ApplicationRunner和CommandLineRunner

相關文章
相關標籤/搜索