springboot源碼深度解析:springboot源碼怎麼看

  前面給大家介紹了SpringBoot啟動的核心流程,本文開始給大家詳細的來介紹SpringBoot啟動中的具體實現的相關細節。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

SpringBoot2.png

SpringApplication構造器

  首先我們來看下在SpringApplication的構造方法中是如何幫我們完成這4個核心操作的。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

 1    @SuppressWarnings({ "unchecked", "rawtypes" })
 2    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
 3        // 傳遞的resourceLoader為null
 4        this.resourceLoader = resourceLoader;
 5        Assert.notNull(primarySources, "PrimarySources must not be null");
 6        // 記錄主方法的配置類名稱
 7        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
 8        // 記錄當前項目的類型
 9        this.webApplicationType = WebApplicationType.deduceFromClasspath();
10        // 加載配置在spring.factories文件中的ApplicationContextInitializer對應的類型並實例化
11        // 並將加載的數據存儲在了 initializers 成員變量中。
12        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
13        // 初始化監聽器 並將加載的監聽器實例對象存儲在了listeners成員變量中
14        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
15        // 反推main方法所在的Class對象 並記錄在了mainApplicationClass對象中
16        this.mainApplicationClass = deduceMainApplicationClass();
17    }

1.webApplicationType

  首先來看下webApplicationType是如何來推導出當前啟動的項目的類型。通過代碼可以看到是通過deduceFromClassPath()方法根據ClassPath來推導出來的。

1this.webApplicationType = WebApplicationType.deduceFromClasspath();

  跟蹤進去看代碼

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

在看整體的實現邏輯之前,我們先分別看兩個內容,第一就是在上面的代碼中使用到了相關的靜態變量。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  這些靜態變量其實就是一些綁定的Java類的全類路徑。第二個就是 ClassUtils.isPresent()方法,該方法的邏輯也非常簡單,就是通過反射的方式獲取對應的類型的Class對象,如果存在返回true,否則返回false

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  所以到此推導的邏輯就非常清楚了

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

2.setInitializers

  然後我們再來看下如何實現加載初始化器的。

1// 加載配置在spring.factories文件中的ApplicationContextInitializer對應的類型並實例化
2        // 並將加載的數據存儲在了 initializers 成員變量中。
3        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));

  首先所有的初始化器都實現了
ApplicationContextInitializer接口,也就是根據這個類型來加載相關的實現類。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

 然後加載的關鍵方法是
getSpringFactoriesInstances()方法。該方法會加載 spring.factories文件中的key為
org.springframework.context.ApplicationContextInitializer 的值。

spring-boot項目下

1# Application Context Initializers
2org.springframework.context.ApplicationContextInitializer=
3org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,
4org.springframework.boot.context.ContextIdApplicationContextInitializer,
5org.springframework.boot.context.config.DelegatingApplicationContextInitializer,
6org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,
7org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

spring-boot-autoconfigure項目下

1# Initializers
2org.springframework.context.ApplicationContextInitializer=
3org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,
4org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

具體的加載方法為 `getSpringFacotiesInstance()`方法,我們進入查看

  先進入
SpringFactoriesLoader.loadFactoryNames(type, classLoader)中具體查看加載文件的過程.

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  然後我們來看下 loadSpringFactories方法

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  通過Debug的方式查看會更清楚哦

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  通過 loadSpringFactories 方法我們看到把 spring.factories文件中的所有信息都加載到了內存中了,但是我們現在只需要加載
ApplicationContextInitializer類型的數據。這時我們再通過 getOrDefault()方法來查看。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  進入方法中查看

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  然後會根據反射獲取對應的實例對象。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  好了到這其實我們就清楚了
getSpringFactoriesInstances方法的作用就是幫我們獲取定義在 META-INF/spring.factories文件中的可以為
ApplicationContextInitializer 的值。並通過反射的方式獲取實例對象。然後把實例的對象信息存儲在了SpringApplication的 initializers屬性中。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

3.setListeners

  清楚了 setInitializers()方法的作用後,再看 setListeners()方法就非常簡單了,都是調用了
getSpringFactoriesInstances方法,只是傳入的類型不同。也就是要獲取的 META-INF/spring.factories文件中定義的不同信息罷了。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  即加載定義在 META-INF/spring.factories文件中聲明的所有的監聽器,並將獲取後的監聽器存儲在了 SpringApplication的 listeners屬性中。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  默認加載的監聽器為:

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

4.mainApplicationClass

  最後我們來看下
duduceMainApplicaitonClass()方法是如何反推導出main方法所在的Class對象的。通過源碼我們可以看到是通過 StackTrace來實現的。

1StackTrace:
2我們在學習函數調用時,都知道每個函數都擁有自己的棧空間。
3一個函數被調用時,就創建一個新的棧空間。那麼通過函數的嵌套調用最後就形成了一個函數調用堆棧

  StackTrace其實就是記錄了程序方法執行的鏈路。通過Debug方式可以更直觀的來呈現。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  那麼相關的調用鏈路我們都可以獲取到,剩下的就只需要獲取每鏈路判斷執行的方法名稱是否是 main就可以了。

SpringBoot源碼分析之SpringApplication構造方法核心源碼分析

image.png

  好了到此相關的4個核心步驟就給大家分析完了,希望對大家能有所幫助哦!

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/223447.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 14:20
下一篇 2024-12-09 14:20

相關推薦

發表回復

登錄後才能評論