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