Spring Boot啟動加載流程自動配置的底層原理(專家解讀)
在使用 Spring Boot 時,開發(fā)者常常會感到驚訝:為什么這么少的配置卻能實現(xiàn)如此豐富的功能?為何啟動一個 Spring Boot 應用可以變得如此簡單便捷?在這個看似平凡的啟動過程中,其實隱藏著一套精妙的自動化機制和源碼邏輯。本文將帶你深入探索 Spring Boot 的啟動流程,逐步揭開自動配置的幕后奧秘。通過了解這些底層原理,你將發(fā)現(xiàn),原來每一次應用的無縫啟動都是精心設計的結果,讓你對 Spring Boot 有更深刻的理解和掌控力!
一、整體概述
(一)基本整體初步分析
Spring Boot 是一個用于構建獨立的、生產(chǎn)級的 Spring 應用程序的框架,它提供了自動化的配置和約定優(yōu)于配置的原則。在理解 Spring Boot 的啟動配置原理之前,我們需要了解幾個關鍵概念。
首先,Spring Boot 使用了基于約定的自動配置機制。它通過在 classpath 下查找特定的配置文件和類,根據(jù)應用程序所使用的依賴自動配置 Spring 應用程序的各種組件。這樣可以大大簡化開發(fā)者的工作,減少了手動配置的需求。
其次,Spring Boot 使用了條件化配置(Conditional Configuration)的機制。這意味著配置的應用取決于一組條件是否滿足。條件可以基于多種因素,如 classpath 中存在特定的類、特定的 bean 是否存在等等。通過條件化配置,Spring Boot 可以根據(jù)不同的環(huán)境和需求進行動態(tài)的配置。
Spring Boot 的啟動配置原理可以概括如下:
- 在啟動過程中,Spring Boot 會加載并解析應用程序的配置文件,其中包括 application.properties 或 application.yml 文件等。這些文件中可以定義各種屬性和配置信息,如數(shù)據(jù)庫連接、日志級別等。
- Spring Boot 會自動掃描 classpath 下的特定包,尋找?guī)в刑囟ㄗ⒔獾念?,?@SpringBootApplication。這個注解標識了一個 Spring Boot 應用程序的入口點。
- 根據(jù)配置文件中的屬性和條件化配置的機制,Spring Boot 自動配置應用程序的各種組件,包括數(shù)據(jù)庫連接池、消息隊列、Web 服務器等。如果需要進行自定義配置,可以使用專門的注解或編寫自定義的配置類。
- 在應用程序啟動時,Spring Boot 會初始化 Spring 容器,并根據(jù)配置進行相應的初始化工作。這包括創(chuàng)建和管理 bean、處理依賴注入等。
總的來說,Spring Boot 的啟動配置原理是基于自動化的約定和條件化配置機制。它通過讀取配置文件、掃描注解、自動配置組件等步驟,簡化了應用程序的配置過程,并提供了靈活性和易用性。
(二)從啟動來看整體過程圖分析
每個SpringBoot程序都有一個主入口main方法,main里面調用SpringApplication.run()啟動整個SpringBoot程序,該方法所在類需要使用@SpringBootApplication注解,例如如下
package org.zyf.javabasic;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* 描述:啟動入口類
*
* @author yanfengzhang
* @date 2019-12-19 18:11
*/
@SpringBootApplication
@ComponentScan(basePackages = {"org.zyf.javabasic"})
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
@EnableSwagger2
public class ZYFApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ZYFApplication.class, args);
}
其中對@SpringBootApplication進行展開分析:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.boot.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.core.annotation.AliasFor;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@AliasFor(
annotation = EnableAutoConfiguration.class
)
String[] excludeName() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackages"
)
String[] scanBasePackages() default {};
@AliasFor(
annotation = ComponentScan.class,
attribute = "basePackageClasses"
)
Class<?>[] scanBasePackageClasses() default {};
}
@SpringBootApplication包括三個注解,功能如下:
- @SpringBootConfiguration(內部為@Configuration):被標注的類等于在spring的XML配置文件中(applicationContext.xml),裝配所有bean事務,提供了一個spring的上下文環(huán)境
- @ComponentScan:組件掃描,可自動發(fā)現(xiàn)和裝配Bean(比如@Component和@Configuration),默認掃描SpringApplication的run方法里類所在的包路徑下所有文件
- @EnableAutoConfiguration:激活SpringBoot自動裝配的特性
現(xiàn)在對主入口main方法進行展開來給出整體的流程圖分析

二、SpringApplication構造過程分析
進入main里面的run方法,創(chuàng)建了一個SpringApplication實例,配置一些基本的環(huán)境變量、資源、構造器、監(jiān)聽器,進入這個SpringApplication有參構造函數(shù)
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}注意:在該構造方法內,做的工作就是把相關的類(主要是initializer和listener)加載進容器中,并沒有執(zhí)行
(一)驗證主配置類不為空并且保存主類

(二)推斷項目的類型

進入對應方法分析如下:

推斷項目的類型可能為reactive、none、servlet三種類型,默認為servlet類型。其使用類加載器判斷類型的邏輯如下
類型 | 判斷情況 |
|---|---|
reactive | 存在Spring WebFlux的DispatcherHandler存在,但是Spring MVC的DispatcherServlet不存在 |
none | 二者都不存在 |
servlet | 剩余所有情況 |
(三)初始化initializers

先進入ApplicationContextInitializer接口,這個接口只有一個方法initialize
package org.springframework.context;
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C var1);
}查看實現(xiàn)了該這個接口的類進行分析

以SharedMetadataReaderFactoryContextInitializer實現(xiàn)類為例,跳轉對應jar包,可以看到里面 spring.factories就在key為ApplicationContextInitializer中指定了對應的實現(xiàn)類,例如:

進入SharedMetadataReaderFactoryContextInitializer,其實現(xiàn)了ApplicationContextInitializer接口,并實現(xiàn)了里面的initialize方法

現(xiàn)在回到一開始再來看getSpringFactoriesInstance()方法,其核心為loadFactoryNames()方法

進入loadFactoryNames()方法,可以看到ApplicationContextInitializer的相關獲取內容直接就是從文件“META-INF/spring.factories”中獲取保存的

(四)加載相關的listeners

先進入ApplicationListener接口,這個接口只有一個方法onApplicationEvent
package org.springframework.context;
import java.util.EventListener;
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E var1);
}查看實現(xiàn)了該這個接口的類進行分析

以BackgroundPreinitializer實現(xiàn)類為例,跳轉對應jar包,可以看到里面 spring.factories就在key為ApplicationListener中指定了對應的實現(xiàn)類:

進入BackgroundPreinitializer,其實現(xiàn)了ApplicationListener,并實現(xiàn)了里面的onApplicationEvent
方法如下:

現(xiàn)在回到一開始再來看getSpringFactoriesInstance()方法,其處理流程和上面的一樣,即依然是從類路徑下找到META-INF/spring.factories配置的所有ApplicationListener
(五)決定ApplicationClass主程序

進入deduceMainApplicationClass方法

三、SpringApplication啟動過程分析

SpringBoot啟動方案,包括啟動流程的監(jiān)聽模塊、加載配置環(huán)境模塊、及核心的創(chuàng)建上下文環(huán)境模塊以及后續(xù)的收尾回調等內容
(一)監(jiān)控器監(jiān)聽容器啟動并進行圖形化頁面處理

(二)監(jiān)聽器SpringApplicationRunListeners開啟監(jiān)聽

直接開始分析ApringApplicationRunListeners,內含SpringApplicationRunListener的集合,其中starting方法就是對listeners進行遍歷,對每個listener都調用starting方法

SpringApplicationRunListener和ApplicationListener都是SpringBoot中的事件監(jiān)聽器,但是它們所監(jiān)聽的事件和觸發(fā)時機有所不同,其區(qū)別如下:
- 監(jiān)聽的事件不同
SpringApplicationRunListener主要監(jiān)聽SpringApplication運行時的各種事件,例如應用程序開始啟動、應用程序啟動失敗、應用程序啟動完成等事件。而ApplicationListener主要監(jiān)聽Spring容器中的各種事件,例如Bean加載完成、上下文刷新完成等事件。 - 觸發(fā)時機不同
SpringApplicationRunListener在SpringApplication啟動時就開始工作,可以接收到應用程序開始啟動、應用程序啟動失敗、應用程序啟動成功等各種事件。而ApplicationListener則是在Spring容器啟動完成后,才能開始工作,監(jiān)聽的是Spring容器中的各種事件。 - 使用場景不同
在實際應用中,SpringApplicationRunListener主要用于監(jiān)聽SpringApplication的啟動過程,例如在應用程序啟動前后執(zhí)行某些操作、監(jiān)聽應用程序啟動失敗事件并做出相應的操作等。而ApplicationListener則用于監(jiān)聽Spring容器中的各種事件,例如在Bean加載完成后做出相應的操作、在上下文刷新完成后更新一些狀態(tài)等。
總之,盡管SpringApplicationRunListener和ApplicationListener都是SpringBoot中的事件監(jiān)聽器,但是它們所監(jiān)聽的事件、觸發(fā)時機、使用場景等都有所不同,我們需要根據(jù)具體的應用需求,選擇合適的監(jiān)聽器來完成應用程序的事件處理。
在進入看一下SpringApplicationRunListener這個類
package org.springframework.boot;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public interface SpringApplicationRunListener {
void starting();
void environmentPrepared(ConfigurableEnvironment environment);
void contextPrepared(ConfigurableApplicationContext context);
void contextLoaded(ConfigurableApplicationContext context);
void started(ConfigurableApplicationContext context);
void running(ConfigurableApplicationContext context);
void failed(ConfigurableApplicationContext context, Throwable exception);
}對應方法說明如下
監(jiān)聽方法 | 運行階段說明 | SpringBoot起始版本 |
|---|---|---|
contextLoaded(ConfigurationApplicationEnvironment) | ConfigurableApplicationContext完成加載,但仍未啟動;通知監(jiān)聽器,ApplicationContext已經(jīng)完成IoC配置 | 1.0 |
contextPrepared(ConfigurationApplicationEnvironment) | ConfigurableApplicationContext準備妥當:通知監(jiān)聽器,ApplicationContext已經(jīng)創(chuàng)建并初始化完成 | 1.0 |
environmentPrepared(ConfigurationEnvironment) | ConfigurationEnvironment準備妥當,允許將其調整 | 1.0 |
failed(ConfigurationApplicationEnvironment,Throwable) | Spring應用運行失敗 | 2.0 |
running(ConfigurationApplicationEnvironment) | Spring應用正在運行 | 2.0 |
started(ConfigurationApplicationEnvironment) | ConfigurableApplicationContext已啟動,此時SpringBean已初始化完成 | 2.0 |
starting() | run方法執(zhí)行的時候立馬執(zhí)行:通知監(jiān)聽器,SpringBoot開始執(zhí)行 | 1.0 |
總的來說就是創(chuàng)建了應用的監(jiān)聽器SpringApplicationRunListeners并調用start()開始監(jiān)聽,先在getRunListeners中獲取了所有的監(jiān)聽器,然后starting開啟
(三)environmentPrepared環(huán)境準備處理

分析這段代碼,進入準備環(huán)境的方法prepareEnvironment中,可以看到如下:

首先創(chuàng)建了一個環(huán)境ConfigurationEnvironment(有的話就獲取,沒有則創(chuàng)建)

回到該方法返回的地方,通過this.configureEnvironment對環(huán)境進行設置,接著如下:

環(huán)境配置好以后回調了SpringApplicationRunListener的environmentPrepared函數(shù),進入該方法:

可以看到environmentPrepared環(huán)境準備中進行了通知監(jiān)聽器,Environment準備完成。
回到開始處,可以看到環(huán)境準備完成后通過bindToSpringApplication將環(huán)境綁定到程序中。
(四)banner打印

打印對應的banner信息

也就是啟動后的改部分,見如下

實際中,改圖可以進行替換,只需要在resources增加banner.txt信息即可,例如如下:

其中的原理可以繼續(xù)點開對應后續(xù)代碼分析,這個后續(xù)中講解替換思路。
(五)創(chuàng)建Spring應用上下文

創(chuàng)建應用上下文即IOC過程,IOC容器是驅動整體SpringBoot應用組件的核心,進入該方法:

這里的創(chuàng)建是根據(jù)SpringApplication在構造階段所推斷的web應用類型進行IOC容器的創(chuàng)建,IOC容器就是run返回的內容。
(六)Spring應用上下文準備階段

prepareContext方法將listeners、environment、applicationArguments、banner等重要組件與上下文對象關聯(lián),對上下文對象進行進一步配置,進入該方法具體分析:

可以看到首先分別保存了剛才生成的environment、ApplicationContext,接下來的applyInitializers方法是執(zhí)行初始化,進入該方法

方法內部遍歷所有的initializer,然后依次回調里面所有的initialize方法(這些initializer就是在springboot剛啟動時構造new springApplication時添加的),設置完當前環(huán)境并完成初始化之后,回調了所有Linsteners的contextPrepared方法

接下來將命令行參數(shù)和banner注冊到IOC容器來,如下:

最后全部操作都完成后,這個方法回調了Listeners的contextLoaded方法,如上。
(七)Spring應用上下文刷新階段

在該方法中首先注冊了一個shutdownHook線程,用來實現(xiàn)SpringBean銷毀生命周期回調

在執(zhí)行完refresh之后的控制臺,可以看到tomcat和一些IOC容器的bean都被加載進去了

(八)Spring應用上下文收尾階段

其中afrerRefresh()并無內容處理,后續(xù)的版本中已經(jīng)沒有改方法了
protected void afterRefresh(ConfigurableApplicationContext context,
ApplicationArguments args) {
}收尾計時器停止,同時調用監(jiān)聽器的started()。
(九)回調工作處理

進入該方法分析

ApplicationContext就是IOC容器,這個方法從IOC容器中獲取了所有的ApplicationRunner和ConmmandLineRunner,接下來進行遍歷和回調。
在callRunners使用的這兩個類幾乎可以等價,都是用于做一些客戶自定義的工作,而且是整個流程完成之后才會調用用戶自己定義的實現(xiàn)類的run方法,這兩個run方法的實現(xiàn)方法都是在容器基本初始化好的時候調用的。
緊接著,如果無異常代碼執(zhí)行如下:

監(jiān)聽器回調running()方法代表SpringApplication正常啟動結束。
(十)SpringApplication啟動異常處理

發(fā)生異常主要是對異常的處理,我們進入該方法分析

可以看到這個異常報告類也是支持自定義并且自動配置的,配置結束后,Springboot做了一些基本的收尾工作,返回了應用環(huán)境上下文(IOC容器)。
四、SpringBoot自動配置分析
Spring Boot 的自動化配置模塊是該框架的核心功能之一,它可以大大簡化應用程序的配置工作。下面是對 Spring Boot 自動化配置模塊的講解和分析:
- 自動化配置的原理:Spring Boot 的自動化配置模塊基于約定優(yōu)于配置的原則。它通過在 classpath 下掃描依賴和配置,自動配置應用程序的各個組件。它使用條件化配置的機制,根據(jù)環(huán)境和條件自動選擇適當?shù)呐渲谩?/strong>
- 自動配置的實現(xiàn)方式:Spring Boot 自動化配置模塊使用了 @Conditional 注解和條件注解來實現(xiàn)條件化配置。這些注解可以根據(jù)一組條件來決定是否啟用某個配置。例如,@ConditionalOnClass 根據(jù) classpath 中是否存在指定的類來判斷是否啟用配置。
- 自動配置的加載順序:Spring Boot 的自動配置是通過在 classpath 下的 META-INF/spring.factories 文件中定義的自動配置類來實現(xiàn)的。這些自動配置類會被自動加載,并根據(jù)條件進行初始化和配置。根據(jù)條件的不同,可以有多個自動配置類被加載,它們會按照優(yōu)先級順序進行配置。
- 自動配置的自定義:Spring Boot 允許開發(fā)者對自動配置進行自定義。你可以使用 @Conditional 注解和條件注解來定義自定義的條件,從而影響自動配置的行為。你還可以使用 @EnableAutoConfiguration 注解來控制自動配置的啟用或禁用。
- 自動配置的好處:Spring Boot 的自動化配置模塊帶來了很多好處。它大大減少了手動配置的工作量,提高了開發(fā)效率。它提供了合理的默認配置,減少了錯誤配置的風險。同時,它的條件化配置機制使得應用程序更具靈活性,能夠根據(jù)不同的環(huán)境和需求進行動態(tài)的配置。
總的來說,Spring Boot 的自動化配置模塊是該框架的重要特性之一。它通過約定優(yōu)于配置的原則和條件化配置機制,實現(xiàn)了自動加載和配置應用程序的各個組件。這為開發(fā)者提供了便利和靈活性,并大大簡化了應用程序的配置過程。
現(xiàn)在回到我們一開始的圖示分析,該配置模塊的主要使用到了SpringFactoriesLoader,即Spring工廠加載器,該對象提供了loadFactoryNames方法,入?yún)閒actoryClass和classLoader,即需要傳入工廠類名稱和對應的類加載器,方法會根據(jù)指定的classLoader,加載該類加器搜索路徑下的指定文件,即spring.factories文件,傳入的工廠類為接口,獲取到這些實現(xiàn)類的類名后,loadFactoryNames方法返回類名集合,方法調用方得到這些集合后,再通過反射獲取這些類的類對象、構造方法,最終生成實例。
(一)自動裝配原理分析
從@SpringBootApplication中的@EnableAutoConfiguration注解中可以看到其import了一個自動配置導入選擇器AutoConfigurationImportSelect
package org.springframework.boot.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}其類圖如下

可以發(fā)現(xiàn)其最終實現(xiàn)了ImportSelector(選擇器)和BeanClassLoaderAware(bean類加載器中間件),其中這個選擇器的作用就是導入組件。
所有自動裝配的邏輯都是在AutoConfigurationImportSelector里面的selectImports方法中實現(xiàn)的

進入getAutoConfigurationEntry()方法

進入getCandidateConfigurations()獲取候選配置方法,可以看到核心的SpringFactoriesLoader的loadFactoryNames()方法

其中SpringFactoriesLoader是Spring Framework工廠機制的加載器,loadFactoryNames是其對應的加載方法,進入這個核心的loadFactoryNames方法中查看

該處加載原理如下:
- 掃描所有jar包路徑下 META-INF/spring.factories,這里是通過類加載器生成對應的url路徑
- 把掃描到的內容包裝成properties對象,并對這個對象的內容進行遍歷,返回map,map的key為接口的全類名,value為接口全部實現(xiàn)類列表(列表里元素去重,防止重復加載),這個value的信息后續(xù)會作為loadSpringFactories方法的返回值
- 在上一步返回的map之中查找并返回指定類名映射的實現(xiàn)類全類名列表
再看剛才getCandidateConfiguration方法中的getSpringFactoriesLoaderFactoryClass方法,返回的就是EnableAutoConfiguration類

也就是說要從剛才properties中再獲取這個類對應的值,把它們加到容器中。
選取mybatis-spring-boot-autoconfigure下的spring.factories文件分析一下:

每一個 xxxAutoConfiguration類都是容器中的一個組件,都加入到容器中,用它們做自動配置;
只有進入到容器中,這些自動配置類才會起作用——進行自動配置功能
(二)條件化自動裝配
對于使用@Configuration的自動配置類,其條件自動化裝配以@condition為核心。在spring底層中的@conditional注解會根據(jù)不同的滿足條件生效整個配置類里面的配置。
條件化裝配可以分為以下幾類:
Class條件注解
注解 | 說明 |
|---|---|
@ConditionalOnClass | 指定類存在時生效 |
@ConditionalOnMissingClass | 指定類缺失時生效 |
Bean條件注解
注解 | 說明 |
|---|---|
@ConditionalOnBean | 指定Bean存在時生效 |
@ConditionalOnMissingBean | 指定Bean缺失時生效 |
屬性條件注解
注解 | 說明 |
|---|---|
@ConditionalOnProperty | 使用屬性(application.properties)的值判斷是否生效 |
Web應用條件注解
注解 | 說明 |
|---|---|
@ConditionalOnWebApplication | 是web類型時生效 |
@ConditionalOnNotWebApplication | 不是web類型時生效 |
其他條件注解
@Conditional擴展注解 | 作用(判斷是否滿足當前指定條件) |
|---|---|
@ConditionalOnJava | 系統(tǒng)的java版本是否符合要求 |
@ConditionalOnExpression | 滿足SpEL表達式指定 |
@ConditionalOnSingleCandidate | 容器中只有一個指定的Bean,或者這個Bean是首選Bean |
@ConditionalOnResource | 類路徑下是否存在指定資源文件 |
@ConditionalOnJndi | JNDI存在指定項 |
分析@ConditionalOnWebApplication
package org.springframework.boot.autoconfigure.condition;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({OnWebApplicationCondition.class})
public @interface ConditionalOnWebApplication {
ConditionalOnWebApplication.Type type() default ConditionalOnWebApplication.Type.ANY;
public static enum Type {
ANY,
SERVLET,
REACTIVE;
private Type() {
}
}
}進入OnWebApplicationCondition類,里面有一個getMatchOutcome()方法,就是判斷是否符合當前配置條件

該方法首先判斷是否使用了這個注釋,然后使用isWebApplication來判斷當前是否是web應用,這些match的方法判斷指定的條件成立,才會給容器添加組件,配置內容才會生效。
(三)自動配置原理舉例:HttpEncodingAutoConfiguration(HTTP編碼自動配置)
可以看到以下信息:
- @Configuration 代表這是一個配置類,類似編寫的配置文件,也可以給容器中添加組件。
- @EnableConfigurationProperties 啟用指定類的ConfigurationProperties功能,將配置文件application.properties的值和ServerProperties綁定起來,并把ServerProperties加入到IOC容器中。
- @ConditionalOnClass用來判斷當前項目是否含有這個類,這里CharacterEncodingFilter的作用就是springMVC亂碼解決的過濾器(以前在spring的xml文件中配置的),如果有這個過濾器則配置生效。
- @ConditionalOnProperty判斷這個配置是否存在,matchIfMissing = true代表即使配置文件中不存在這個屬性也是默認生效的。
需要注意的是,在spring.factories中的自動配置類不是都能生效的,都有各自的生效條件。根據(jù)當前不同條件判斷,來決定這個配置類是否生效;一旦配置類生效,這個配置類就會給容器添加各種組件,這些組件的屬性從對應的properties中獲取,這些類里面的每一個屬性又是和配置文件綁定的。
五、總結
Spring Boot 的自動化配置和啟動流程為開發(fā)者提供了簡化的開發(fā)體驗,降低了配置和啟動的復雜性。通過深入理解 SpringApplication 的啟動步驟、自動配置的原理以及 Spring Boot 如何無縫集成各類組件,我們不僅能更好地運用 Spring Boot,還能更靈活地定制和優(yōu)化應用。自動配置是 Spring Boot 的核心之一,它通過精巧的條件判斷實現(xiàn)了“按需配置”,確保應用在減少冗余的前提下獲得所需的功能支持。
在實際開發(fā)中,理解這些原理可以幫助我們在遇到問題時更快找到原因,尤其是當我們需要進行調優(yōu)或者定制配置時,更能從容應對。希望通過本文的分析,你能夠更全面地掌握 Spring Boot 的核心機制,并在實際項目中充分發(fā)揮它的優(yōu)勢。
到此這篇關于Spring Boot啟動加載流程自動配置的底層原理的文章就介紹到這了,更多相關Spring Boot啟動過程與自動配置內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java網(wǎng)絡編程UDP實現(xiàn)消息發(fā)送及聊天
這篇文章主要為大家詳細介紹了Java網(wǎng)絡編程UDP實現(xiàn)消息發(fā)送及聊天,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07
MybatisPlus查詢條件空字符串和NULL問題背景分析
文章詳細分析了MybatisPlus在處理查詢條件時,空字符串和NULL值的問題,MP 3.3.0及以上版本提供了多種解決方法,包括在Bean屬性上使用注解、全局配置等,推薦使用全局配置的方式來解決這個問題,以避免在SQL查詢中出現(xiàn)不必要的空字符串條件,感興趣的朋友跟隨小編一起看看吧2025-03-03
Java 實戰(zhàn)項目之誠途旅游系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SpringBoot+Vue+maven+Mysql實現(xiàn)一個精美的物流管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11
Jenkins初級應用之Invoke?Phing?targets插件配置
這篇文章主要為大家介紹了Jenkins初級應用之Invoke?Phing?targets的插件配置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪<BR>2022-04-04
Java實戰(zhàn)之圖書管理系統(tǒng)的實現(xiàn)
這篇文章主要介紹了如何利用Java語言編寫一個圖書管理系統(tǒng),文中采用的技術有Springboot、SpringMVC、MyBatis、ThymeLeaf 等,需要的可以參考一下2022-03-03

