SpringBoot配置文件啟動加載順序的方法步驟
前言
Spring Boot的啟動加載順序是一個涉及多個步驟和組件的過程。Spring Boot通過一系列默認設置簡化了應用程序的配置,使得開發(fā)者能夠快速地搭建和部署應用。為了實現(xiàn)這一目標,Spring Boot采用了一種分層和優(yōu)先級機制來加載配置文件。
一、Spring Boot 配置文件的加載順序
1)bootstrap.properties 或 bootstrap.yml (如果存在)
application.properties 或 application.yml
2)命令行參數(shù)
3)操作系統(tǒng)環(huán)境變量
4)從 RandomValuePropertySource 生成的 random.* 屬性
5)由 @TestPropertySource 注解聲明的屬性
6)由 @SpringBootTest 注解并且 #properties 注解屬性的測試屬性
7)由 SpringBootApplication 注解的 exclude 屬性排除的自動配置的類
8)由應用程序的 RandomValuePropertySource 生成的 random.* 屬性
9)在 application.properties 或 application.yml 中使用 SpringApplication 的 setDefaultProperties 方法設置的屬性
這個加載順序是有意為此的,因為有些屬性需要在后續(xù)加載的時候覆蓋前面的同名屬性。
這里是一個簡單的例子,演示如何使用 bootstrap.properties 來配置一些在 Spring Boot 啟動時需要的屬性:
bootstrap.properties
# bootstrap.properties spring.application.name=myapp spring.profiles.active=prod
或者 application.yml
:
# application.yml server: port: 8080
命令行參數(shù)可以用于覆蓋特定的屬性,例如:
java -jar myapp.jar --server.port=9090
二、在Spring Boot中,配置文件的加載順序遵循以下步驟
- 自動加載:Spring Boot在啟動時會掃描特定位置的配置文件。這些位置包括jar包內(nèi)的classpath路徑、當前項目的根目錄以及桌面上的文件路徑。Spring Boot會優(yōu)先加載高優(yōu)先級的配置文件,并在低優(yōu)先級配置文件被加載時覆蓋掉沖突的屬性。
- 自定義配置文件:開發(fā)者可以通過spring.config.name屬性指定自定義配置文件名。Spring Boot會按照以下順序查找這些配置文件:application.和application-default.,并根據(jù)擴展名的優(yōu)先級進行加載。擴展名包括:.properties、.xml、.yml、.yaml。
- 命令行參數(shù):開發(fā)者可以在命令行中指定一些參數(shù)來覆蓋默認的配置值。這些參數(shù)將優(yōu)先于任何其他配置文件中的值生效。
- 環(huán)境變量:環(huán)境變量也可以用來覆蓋配置文件中的屬性值。這些變量在應用程序啟動時自動加載,無需額外操作。
- 屬性占位符:在配置文件中,可以使用${...}語法來引用其他屬性的值。這種方式可以創(chuàng)建依賴關系,使得某些屬性在其他屬性被解析后才能確定其值。
- 自動配置類:Spring Boot提供了一系列的自動配置類,可以根據(jù)項目需求自動配置一些組件。開發(fā)者可以通過禁用特定的自動配置類或自定義自動配置類來覆蓋默認設置。
- 條件注解:Spring Boot允許使用條件注解來控制特定組件的創(chuàng)建。例如,只有當某個屬性存在或滿足特定條件時,某個bean才會被創(chuàng)建。
- 外部化配置:Spring Boot支持將部分配置移動到外部屬性文件中,以提高可維護性和復用性。這些外部屬性文件可以包含在jar包內(nèi)部、當前項目根目錄或其他指定位置。
總結(jié)來說,Spring Boot的配置加載順序遵循以下原則:優(yōu)先從高優(yōu)先級的源加載配置,并在低優(yōu)先級源加載時覆蓋沖突的屬性;開發(fā)者可以通過自定義配置文件、命令行參數(shù)和環(huán)境變量來覆蓋默認值;自動配置類和條件注解允許更靈活地控制組件的創(chuàng)建;而外部化配置則提高了應用程序的維護性和復用性。了解這個加載順序有助于更好地管理和優(yōu)化Spring Boot應用程序的配置。
關鍵步驟劃分的Spring Boot啟動加載順序的概述:
三、啟動準備階段
- 裝載核心啟動器類:
org.springframework.boot.SpringApplication
。 - 通過構(gòu)造函數(shù)創(chuàng)建
SpringApplication
實例時,進行一系列的初始化工作。
四、配置加載階段
- Spring Boot項目會按照特定的順序加載配置文件,這些配置文件可以是application.properties或application.yml格式。
配置文件的加載順序(優(yōu)先級由高到低):
- file:./config/(項目根路徑下的config文件夾)
- file:./(項目根路徑)
- classpath:/config/(類路徑下的config文件夾)
- classpath:/(類路徑)
外部配置文件的加載方式:
- 命令行參數(shù):可以直接在啟動命令后添加啟動參數(shù)。
- spring.config.location:用于指定配置文件的新位置。
如果多個文件有相同的key,高優(yōu)先級的值會覆蓋低優(yōu)先級的值。
五、上下文準備階段
- 準備并刷新應用上下文(Context)。
- 加載所有的初始化器(如從
META-INF/spring.factories
配置文件中加載的)。 - 加載所有的監(jiān)聽器(也是從
META-INF/spring.factories
配置文件中加載的)。
六、啟動執(zhí)行階段
- 觸發(fā)所有
CommandLineRunner
執(zhí)行。 - 執(zhí)行自定義的初始化邏輯(如果有的話)。
七、完成階段
- 啟動完成,等待退出。
注意
- 帶profile的配置文件(如
application-dev.yml
)通常具有比不帶profile的配置文件(如application.yml
)更高的優(yōu)先級。
代碼演示,項目啟動成功后執(zhí)行一段初始化邏輯:
八、啟動main方法中添加初始化邏輯
在Spring Boot的main入口啟動方法中,執(zhí)行SpringApplication.run(LimitApplication.class, args)是可以返回ApplicationContext對象的,我們可以從ApplicationContext中獲取指定的bean對象,執(zhí)行初始化邏輯。
@SpringBootApplication(scanBasePackages = {"com.xinda.springbootday01.service"}) public class OrderApplication { public static void main(String[] args){ //啟動的run方法 ApplicationContext context = SpringApplication.run(OrderApplication.class, args); //啟動執(zhí)行操作:從context中獲取指定的bean,調(diào)度初始化邏輯 OrderService orderService = (OrderService)context.getBean("OrderServiceImpl"); orderService.preLoadCache(); } }
初始化邏輯:
@Service public class OrderServiceImpl implements OrderService { @Override public void preLoadCache(){ System.out.println("應用啟動完成:開始執(zhí)行緩存預加載操作"); } }
九、實現(xiàn)ApplicationRunner或CommandLineRunner接口
在Spring Boot框架中,給我們提供了ApplicationRunner和CommandLineRunner接口來幫助我們解決項目啟動后的初始化資源操作。
如果有多個ApplicationRunner、CommandLineRunner的實現(xiàn)類,可以通過@Order注解進行排序,參數(shù)值小的先執(zhí)行。
實現(xiàn)CommandLineRunner接口:
@Order(1) @Component @Slf4j public class CommandLineRunnerImpl implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("應用啟動完成,開始執(zhí)行CommandLineRunner方法完成資源初始化"); } }
實現(xiàn)ApplicationRunner接口:
@Order(2) @Component @Slf4j public class ApplicationRunnerImpl implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("應用啟動完成,開始執(zhí)行ApplicationRunner方法完成資源初始化"); } }
源碼分析:在SpringApplication的run方法中,有這么一段核心代碼
public ConfigurableApplicationContext run(String... args) { long startTime = System.nanoTime(); DefaultBootstrapContext bootstrapContext = this.createBootstrapContext(); ConfigurableApplicationContext context = null; this.configureHeadlessProperty(); SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(bootstrapContext, this.mainApplicationClass); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments); this.configureIgnoreBeanInfo(environment); Banner printedBanner = this.printBanner(environment); context = this.createApplicationContext(); context.setApplicationStartup(this.applicationStartup); this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); this.refreshContext(context); this.afterRefresh(context, applicationArguments); Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup); } listeners.started(context, timeTakenToStartup); this.callRunners(context, applicationArguments); } catch (Throwable var12) { this.handleRunFailure(context, var12, listeners); throw new IllegalStateException(var12); } try { Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime); listeners.ready(context, timeTakenToReady); return context; } catch (Throwable var11) { this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null); throw new IllegalStateException(var11); } }
十、ApplicationListener監(jiān)聽啟動完成事件
通過源碼,我們發(fā)現(xiàn)在Spring Boot啟動過程中,框架內(nèi)部定義了很多事件SpringApplicationEvent,用來通知SpringApplicationRunListeners監(jiān)聽器,以針對各種事件執(zhí)行對應的邏輯處理。而Spring Boot啟動完成的事件對應的是ApplicationStartedEvent,我們可以通過自定義監(jiān)聽器來監(jiān)聽ApplicationStartedEvent事件,然后執(zhí)行初始化資源的相關操作。
@Component class StartedEventListener implements ApplicationListener<ApplicationStartedEvent> { @Override public void onApplicationEvent(ApplicationStartedEvent event) { System.out.println("應用啟動完成,通知監(jiān)聽器執(zhí)行緩存預加載操作"); } }
總結(jié)
Spring Boot支持兩種類型的配置文件:application.properties和application.yml。當同一個目錄下同時存在這兩種類型的配置文件時,application.properties會優(yōu)先加載,但兩種文件會進行互補配置。即,如果同一配置項在兩個配置文件中都進行了設置,那么application.properties中的配置會覆蓋application.yml中的配置。
除了上述默認的配置文件加載位置外,Spring Boot還支持多種外部配置方式,它們的優(yōu)先級從高到低如下:
1)命令行參數(shù):通過java -jar命令啟動應用時,可以在命令后附加–配置項=值的形式來指定配置。
2)來自java:comp/env的JNDI屬性。
3)Java系統(tǒng)屬性(System.getProperties())。
4)操作系統(tǒng)環(huán)境變量。
5)RandomValuePropertySource配置的random.*屬性值:用于生成隨機值。
6)jar包外部的帶profile的配置文件(如application-{profile}.properties或application-{profile}.yml)。
7)jar包內(nèi)部的帶profile的配置文件。
8)jar包外部的不帶profile的配置文件(如application.properties或application.yml)。
9)jar包內(nèi)部的不帶profile的配置文件。
(由jar包外向jar包內(nèi)進行尋找,優(yōu)先加載帶profile的,再加載不帶profile的。)
10)@Configuration注解類上的@PropertySource。
11)通過SpringApplication.setDefaultProperties指定的默認屬性。
另外,可以通過spring.config.location屬性來改變默認的配置文件位置。
在項目打包后,可以使用命令行參數(shù)的形式來指定配置文件的新位置,指定的配置文件和默認加載的配置文件會共同起作用,形成互補配置。
當使用多環(huán)境配置時(如開發(fā)、測試、生產(chǎn)環(huán)境),可以通過激活不同的profiles來加載對應的配置文件。
到此這篇關于SpringBoot配置文件啟動加載順序的方法步驟的文章就介紹到這了,更多相關SpringBoot配置文件啟動加載順序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- springboot無法加載yml配置文件的解決方案
- SpringBoot使用不同環(huán)境動態(tài)加載不同配置文件
- SpringBoot配置文件的優(yōu)先級順序、加載順序、bootstrap.yml與application.yml區(qū)別及說明
- SpringBoot項目部署時application.yml文件的加載優(yōu)先級和啟動腳本問題
- SpringBoot中的配置文件加載優(yōu)先級詳解
- SpringBoot加載不出來application.yml文件的解決方法
- SpringBoot項目加載配置文件的6種方式小結(jié)
- SpringBoot實現(xiàn)配置文件自動加載和刷新的示例詳解
- SpringBoot的配置文件application.yml及加載順序詳解
- springboot加載配值文件的實現(xiàn)步驟
相關文章
使用SpringBoot Actuator監(jiān)控應用示例
Actuator是Spring Boot提供的對應用系統(tǒng)的自省和監(jiān)控的集成功能,可以對應用系統(tǒng)進行配置查看、相關功能統(tǒng)計等。這篇文章主要介紹了使用SpringBoot Actuator監(jiān)控應,有興趣的可以了解一下2018-05-05使用Spring?Cloud?Stream處理事件的示例詳解
Spring?Cloud?Stream?是基于?Spring?Boot?的用于構(gòu)建消息驅(qū)動微服務的框架,本文主要介紹了如何使用?Spring?Cloud?Stream?來處理事件,需要的可以參考一下2023-06-06解決工具接口調(diào)用報錯:error:Unsupported Media Type問題
當遇到"UnsupportedMediaType"錯誤時,意味著HTTP請求的Content-Type與服務器期望的不匹配,比如服務器期待接收JSON格式數(shù)據(jù),而發(fā)送了純文本格式,常見的Content-Type類型包括text/html、application/json、multipart/form-data等2024-10-10Java開發(fā)常見錯誤之數(shù)值計算精度和舍入問題詳析
除了使用Double保存浮點數(shù)可能帶來精度問題外,更匪夷所思的是這種精度問題,下面這篇文章主要給大家介紹了關于Java開發(fā)常見錯誤之數(shù)值計算精度和舍入問題的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-11-11在IntelliJ?IDEA中配置SSH服務器開發(fā)環(huán)境并實現(xiàn)固定地址遠程連接的操作方法
本文主要介紹如何在IDEA中設置遠程連接服務器開發(fā)環(huán)境,并結(jié)合Cpolar內(nèi)網(wǎng)穿透工具實現(xiàn)無公網(wǎng)遠程連接,然后實現(xiàn)遠程Linux環(huán)境進行開發(fā),本例使用的是IDEA2023.2.5版本,感興趣的朋友跟隨小編一起看看吧2024-01-01Spring @async方法如何添加注解實現(xiàn)異步調(diào)用
這篇文章主要介紹了Spring @async方法如何添加注解實現(xiàn)異步調(diào)用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-01-01