深入理解SpringBoot中bootstrap和application的区别[源码分析/图文亲测]

一、前言

关于springboot中bootstrap和application的区别,网上很多文章可能讲述的并不清晰,尤其是根据网上的讲解对比自己的测试,出入很大,本质原因都是理解不深刻和表述不清楚所致。

因此花了一些时间,通过debug源码方式,来深入分析两者的不同。

二、效果演示

bootstrap和application的区别主要集中在加载优先级,以及对bootstrap中的一些属性配置是否可以被application覆盖的问题。

properties配置文件为例(properties和yml等优先级本篇不做分析),创建bootstrap.properties和applicatoin.properties

在bootstrap.properties中仅配置端口号为

server.port=8081

在application.properties中仅配置端口号为:

server.port=8082

在bootstrap.properties和application.properties同时存在时,启动控制台,查看当前端口:

 通过后台日志看到,端口号为8082,以applicaiton.properties中的配置为准,也就是application.properties覆盖了bootstrap.properties中的配置,并且生效。

三、修改配置属性

在bootstrap.properties中修改配置,新增spring.profiles.include属性

server.port=8081
spring.profiles.include=test

application.properties同理

server.port=8082
spring.profiles.include=prod

spring.profiles.include的作用:

例如项目分为开发、测试、生产三个不同阶段(环境),每个阶段都会有db、redis等的不同配置信息,例如application-test.properties、application-prod.properties等。

application-test.properties文件配置:

server.port=8083

application-prod.properties文件配置:

server.port=8080

根据第二步的加载逻辑,application.properties(端口8082)会覆盖bootstrap.properties(端口8081)中的配置,在applicaton.properties中引入了prod配置项,也就是最终应该以application-prod.properties文件中的端口8080为启动端口,运行项目:

启动端口居然为 8083 !!! 

也就是实际生效的配置文件为application-test.properties。

四、源码分析

对与三和四的不同效果,也是网上困惑最多的点,我们通过阅读源码的方式,梳理一下加载流程。

1、特殊属性

打开ConfigFileApplicationListener.java(源码在spring-boot-2.3.7.RELEASE.jar)

static {
		Set<String> filteredProperties = new HashSet<>();
		filteredProperties.add("spring.profiles.active");
		filteredProperties.add("spring.profiles.include");
		LOAD_FILTERED_PROPERTY = Collections.unmodifiableSet(filteredProperties);
	}

	/**
	 * The "active profiles" property name.
	 */
	public static final String ACTIVE_PROFILES_PROPERTY = "spring.profiles.active";

	/**
	 * The "includes profiles" property name.
	 */
	public static final String INCLUDE_PROFILES_PROPERTY = "spring.profiles.include";

	/**
	 * The "config name" property name.
	 */
	public static final String CONFIG_NAME_PROPERTY = "spring.config.name";

	/**
	 * The "config location" property name.
	 */
	public static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";

	/**
	 * The "config additional location" property name.
	 */
	public static final String CONFIG_ADDITIONAL_LOCATION_PROPERTY = "spring.config.additional-location";

上属性在bootstrap的配置项有优先加载,而且不会被application配置文件覆盖

2、bootstrap优先加载

为什么bootstrap中的属性会优先加载

在启动springboot时,通过debug跟踪启动类的加载顺序可知,BootstrapApplicationListener的加载顺序非常靠前,并且代码中指定了配置文件的最先加载名称为bootstrap(在springboot中文件名和文件后缀分开加载) 。

3、固有属性加载

 优先加载ACTIVE_PROFILES_PROPERTY和INCLUDE_PROFILES_PROPERTY

	/**
	 * The "active profiles" property name.
	 */
	public static final String ACTIVE_PROFILES_PROPERTY = "spring.profiles.active";

	/**
	 * The "includes profiles" property name.
	 */
	public static final String INCLUDE_PROFILES_PROPERTY = "spring.profiles.include";

bootstrap.properties中配置的spring.profiles.include为test,上图debug中也优先加载test

3、加载application

继续debug,application配置文件中指定的prod属性也开始被加载

其中test为existingProfiles,也就是已经加载的属性

prod为includeProfiles,是当前刚刚获取的属性。

bootstrap和application中的属性配置已完成加载。

4、配置解析

配置加载后,开始去读,其中profiles为一个队列,列表中加载了prod和test两个属性,最后读取的最先处理,列表中prod排在最前,先poll(),如下图:

 同理,test最后加载,以application-test.properties配置文件为准,端口为8083。

5、结果分析

通过以上分析可以清楚了解:
 

优先级:bootstrap优先执行,application在bootstrap加载后再执行

作用域:bootstrap作为系统环境配置项,application作为服务应用配置,可以简单将bootstrap比喻为虚拟机,application为虚拟机中运行的程序。

属性配置:一般和应用相关的在application中配置,和系统环境相关或者固定基本不会改动的参数在bootstrap中配置。

注意事项:即便了解了上述过程,配置时,尽量避免bootstrap和application中配置相同属性。

  • 12
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月夜烛峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值