Spring boot属性文件加载和生效顺序深度分析

简介: spring boot最核心的特性就是自动化配置,我们在学习spring boot的时候,首要需要了解它的自动化配置原理,其次是属性文件的加载顺序,我认为这两点是学习spring boot的重中之中。

网上介绍spring boot属性文件的加载顺序的文章很多,但都没有从源码上深入分析。

今天和大家一起通过源码探究,spring boot属性文件的加载顺序。


这里先说明一点:

先加载的属性未必会生效,后加载的属性未必一定会覆盖先加载的属性值。


说明:

加载指的是将属性值读取加载到spring容器中的过程;

生效指的是运用加载到的属性值去初始化bean的过程。


属性值加载的顺序,和属性值生效的顺序没有必然的关系。


为什么要分析?


主要是在实际项目开发过程中,由于属性文件非常多,常常导致属性文件配置混乱,

最常遇到的问题就是:

为什么明明配置了属性,但项目启动就是怎么都不生效的问题?

所以,搞清楚属性文件的读取和生效的顺序,对日常基于spring boot的开发过程中非常重要。


源码分析


1、通过main启动类,找到doInvokeListener()方法建立断点,观察ApplicationEvent中属性源的变化情况:

说明:测试的工程注册在eurake中,并从配置中心config中加载属性。

63.png


2、最先加载的3个属性源

62.png

Inlined Test Properties 单元测试属性

systemProperties JVM系统属性

SystemEnvironmentProperty 系统环境变量属性


3、初始化ConfigFileApplicationListener监听器时,新加载了如下数据源

61.png

configurationProperties

配置属性源,这个属性源比较特殊,他不会去自己加载配置属性,而是将environment中已经加载到的属性源按顺序放入存放进来,并将自己放到propertySourceList的头部first。(不是很好理解,个人感觉可能是一种缓存机制)

random 随机数属性源

springCloudClientHostInfo spring cloud客户端host相关属性源

bootstrap-dev.properties

bootstrap.properties

defaultProperties


4、加载配置中心属性

60.png

可以发现,配置中心属性源configService虽然是后面加载的,但是被放在了propertySourceList的头部。


5、启动完成后,environment中propertySourceList的顺序

59.png

feign feign调用的属性源

systemProperties java se运行时系统属性

SystemEnvironmentProperty 系统环境变量属性

configService 配置中心属性源

configurationProperties 配置属性源

Inlined Test Properties 单元测试属性

random 随机数属性源

application-dev.propeties application-profile属性源

application.propeties application属性源

springCloudClientHostInfo spring cloud客户端host相关属性源

bootstrap-dev.propeties bootstrap-profile属性源

bootstrap.propeties bootstrap属性源

eureka/server.properties eureka服务属性源

defaultProperties 默认属性源


6、读取属性文件的源码分析

58.png


springboot 启动时,会初始化各种属性源PropertySource,并把加载的属性源存放到 enviroment 的propertySourceList中。我们在获取属性时,通过遍历propertySourceList的属性源去读取属性值,获取对应属性值就直接返回(先读取先生效),所以在propertySourceList前面的属性源会优先生效。


注意propertySourceList的类型是 CopyOnWriteArrayList ,即线程安全的ArrayList


7、开启属性获取日志,监控属性获取过程


logging.level.org.springframework.core.env=trace

57.png



通过注入Environment,查看执行属性加载顺序


@SpringBootTest
@Slf4j
class DemoApplicationTests {
    @Autowired
    Environment environment;
    @Test
    void getProperties() {
        System.out.println(environment.getProperty("spring.user.name"));
    }
}


properties和yml配置文件加载顺序


一般在spring boot中最好统一只使用一种类型的配置文件,避免出现配置混乱。

yml配置文件具有更好的格式,更强大的功能,但是对属性文件的配置格式要求比较。格式出错导致属性读取不到的问题比较难排查,且利用属性的键值搜索指定属性时,也不是很方便。properties属性文件,好处就是简单,不容易出现格式方面的问题,便于属性查找。

假设一个项目在同一位置同时存在application.properties和application.yml文件,


且其中都含有相同的某个key,但value不同,如:


application.properties中:

server.port=8001,


application.yml中:

server.port=8888。


问题:springboot是否都加载这两个配置文件?如果两个文件有相同的key,取哪一个文件的value?


答: 都加载,且按properties→yml的顺序加载。

56.png

在看到spring.factories中,配置加载器顺序是先执行PropertiesPropertySourceLoader再到YamlPropertySourceLoader。


在ConfigFileApplicationListener获取server.port这个key的value时候,可以发现两配置文件全都加载进去了,且注意顺序,application.properties文件在前。

55.png

getSource()方法获取到两个Source,先从application.properties文件中查找值,一旦找到立即返回,如果找不到再从application.yml中查找。


总结


1、spring boot中先读取的属性不一定先生效,生效的顺序是根据bean初始化时,environment中属性源propertySourceList的顺序来决定的。


2、属性源初始化读取的顺序和最后存放到environment中的propertySourceList的顺序没有必然关系。

environment.getPropertySources().addFirst(source);
    environment.getPropertySources().addAfter(source1,source2);
    environment.getPropertySources().addBefore(source1,source2);
    environment.getPropertySources().addLast(source);


3、属性文件的读取顺序大概是:

java se运行时系统属性 ——》系统环境变量属性——》

bootstrap.properties——》bootstrap-dev.properties ——》configService 配置中心属性源——》application属性源——》 application-dev属性源


注意:

从属性源的加载顺序就可以看出,为什么我们在微服务里面,在业务服务模块进行配置中心配置的时候,一定要在bootstrap属性文件中配置了。


4、项目中yml和properties这两个格式的配置文件,一般只选用一种类型的配置文件。

如果同时配置两种,会优先加载properties的配置文件,且properties的配置属性会优先生效。


5、属性文件的生效的顺序大致是:

java se运行时系统属性 ——》 系统环境变量属性——》

configService 配置中心属性——》application-dev属性源——》 application属性源——》bootstrap-dev.properties ——》bootstrap.properties

我们在java -jar启动脚本中配置的属性,属于 java se运行时系统属性,优先级最高。


6、如果项目中发现配置的属性一直没有生效,可以参考属性源的生效顺序,看看是否出现属性覆盖的问题。

更直接的方式是通过单元测试,执行environment.getProperty(“spring.user.name”),查看属性源列表propertySourceList的顺序,并通过打印日志来判断属性值是从具体哪个属性源加载到的。


希望看完本篇文章,当再被问到spring boot属性文件的加载顺序的时候,你可以胸有成竹的款款而谈。


https://www.jianshu.com/p/256e6019349d


目录
相关文章
|
2月前
|
安全 NoSQL Java
SpringBoot接口安全:限流、重放攻击、签名机制分析
本文介绍如何在Spring Boot中实现API安全机制,涵盖签名验证、防重放攻击和限流三大核心。通过自定义注解与拦截器,结合Redis,构建轻量级、可扩展的安全防护方案,适用于B2B接口与系统集成。
409 3
|
3月前
|
JavaScript Java 应用服务中间件
基于springboot的学生成绩分析和弱项辅助系统
本系统旨在解决学生成绩分析与弱项辅助信息管理效率低下的问题,通过软件技术实现数据处理的高效化、流程化与规范化,提升管理质量与便捷性。
|
8月前
|
Java 测试技术 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
本课主要讲解Spring Boot项目中的属性配置方法。在实际开发中,测试与生产环境的配置往往不同,因此不应将配置信息硬编码在代码中,而应使用配置文件管理,如`application.yml`。例如,在微服务架构下,可通过配置文件设置调用其他服务的地址(如订单服务端口8002),并利用`@Value`注解在代码中读取这些配置值。这种方式使项目更灵活,便于后续修改和维护。
118 0
|
4月前
|
XML 人工智能 IDE
Springboot整合SSMP报错分析
本文介绍了Springboot整合SSMP框架时常见的报错及解决方案,包括MyBatis-Plus版本不兼容导致的Lambda表达式条件构造器报错及表名不匹配问题。通过升级或降级MyBatis-Plus版本、使用@TableName注解或配置table-prefix属性,可有效解决上述问题,帮助开发者避免在整合SSMP时出现不必要的错误。
209 0
|
5月前
|
负载均衡 Java API
基于 Spring Cloud 的微服务架构分析
Spring Cloud 是一个基于 Spring Boot 的微服务框架,提供全套分布式系统解决方案。它整合了 Netflix、Zookeeper 等成熟技术,通过简化配置和开发流程,支持服务发现(Eureka)、负载均衡(Ribbon)、断路器(Hystrix)、API网关(Zuul)、配置管理(Config)等功能。此外,Spring Cloud 还兼容 Nacos、Consul、Etcd 等注册中心,满足不同场景需求。其核心组件如 Feign 和 Stream,进一步增强了服务调用与消息处理能力,为开发者提供了一站式微服务开发工具包。
558 0
|
10月前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
2375 17
Spring Boot 两种部署到服务器的方式
|
7月前
|
SQL 前端开发 Java
深入分析 Spring Boot 项目开发中的常见问题与解决方案
本文深入分析了Spring Boot项目开发中的常见问题与解决方案,涵盖视图路径冲突(Circular View Path)、ECharts图表数据异常及SQL唯一约束冲突等典型场景。通过实际案例剖析问题成因,并提供具体解决方法,如优化视图解析器配置、改进数据查询逻辑以及合理使用外键约束。同时复习了Spring MVC视图解析原理与数据库完整性知识,强调细节处理和数据验证的重要性,为开发者提供实用参考。
298 0
|
8月前
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——指定项目配置文件
在实际项目中,开发环境和生产环境的配置往往不同。为简化配置切换,可通过创建 `application-dev.yml` 和 `application-pro.yml` 分别管理开发与生产环境配置,如设置不同端口(8001/8002)。在 `application.yml` 中使用 `spring.profiles.active` 指定加载的配置文件,实现环境快速切换。本节还介绍了通过配置类读取参数的方法,适用于微服务场景,提升代码可维护性。课程源码可从 [Gitee](https://gitee.com/eson15/springboot_study) 下载。
309 0
|
8月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot中的项目属性配置——少量配置信息的情形
在微服务架构中,随着业务复杂度增加,项目可能需要调用多个微服务。为避免使用`@Value`注解逐一引入配置的繁琐,可通过定义配置类(如`MicroServiceUrl`)并结合`@ConfigurationProperties`注解实现批量管理。此方法需在配置文件中设置微服务地址(如订单、用户、购物车服务),并通过`@Component`将配置类纳入Spring容器。最后,在Controller中通过`@Resource`注入配置类即可便捷使用,提升代码可维护性。
137 0
|
10月前
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
218 5