前言
在 Spring Boot 开发中,配置文件是项目灵活部署和动态调整的核心机制。理解配置文件的加载原理,能帮助开发者高效管理不同环境的配置、解决配置冲突问题,并灵活扩展项目的可配置性。本文将结合 Spring Boot 的设计机制,深入解析配置文件的加载逻辑与实践技巧。
一、Spring Boot 配置文件的类型与格式
Spring Boot 支持多种格式的配置文件,不同格式适用于不同的开发场景:
1. application.properties
格式:传统的键值对格式,通过#添加注释。
示例:
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test
适用场景:简单配置场景,适合习惯传统配置方式的开发者。
2. application.yml/application.yaml
格式:YAML 格式,通过缩进表示层级关系,使用#注释。
示例:
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
优势:结构清晰,层级关系直观,适合复杂配置场景。
3. 其他格式
环境变量:通过操作系统环境变量注入配置(如JAVA_OPTS)。
命令行参数:启动时通过--key=value传递配置(如java -jar app.jar --server.port=8081)。
二、配置文件的加载顺序与优先级
Spring Boot 加载配置文件时遵循严格的顺序,优先级从高到低依次为:
1. 命令行参数
直接通过命令行传递的参数优先级最高,会覆盖其他任何配置。
示例:--spring.datasource.url=jdbc:mysql://new-host:3306/test
2. 来自SPRING_APPLICATION_JSON的属性
通过环境变量SPRING_APPLICATION_JSON传递的 JSON 格式配置,支持层级结构。
示例:
export SPRING_APPLICATION_JSON='{"server":{"port":8082}}'
3. 操作系统环境变量
操作系统层面的环境变量,如数据库连接信息、端口号等。
注意:环境变量中的点(.)需转为下划线(_),如SPRING_DATASOURCE_URL对应spring.datasource.url。
4. JNDI 属性(如 Tomcat 服务器)
从 Java 命名目录接口(JNDI)获取的配置,通常用于传统企业级部署场景。
5. Java 系统属性(System.getProperties())
通过-D参数传递的系统属性,如-Dspring.datasource.url=...。
6. RandomValuePropertySource 配置的随机值
用于生成随机数或 UUID,如secret=${random.uuid}。
7. 应用配置文件(按加载顺序)
Spring Boot 会从以下位置按顺序加载配置文件,后加载的文件会覆盖先加载的同名配置:
(1)当前项目的src/main/resources/目录
(2)当前项目的src/main/resources/config/目录
(3)jar 包外的./config/目录(相对于启动类路径)
(4)jar 包外的./目录(相对于启动类路径)
示例优先级验证:
若src/main/resources/application.properties和./config/application.properties同时存在同一份server.port配置,则后者的值会覆盖前者。
三、多环境配置与激活
Spring Boot 通过spring.profiles机制支持多环境配置(如开发、测试、生产),核心机制如下:
1. 多环境配置文件命名规则
主配置文件:application.properties(或.yml),存放公共配置。
环境特定配置文件:application-{profile}.properties,如:
application-dev.properties(开发环境)
application-sit.properties(测试环境)
application-uat.properties(预发布环境)
application-prod.properties(生产环境)
2. 激活指定环境
通过以下方式指定当前激活的环境:
配置文件中指定:在主配置文件中添加spring.profiles.active=dev。
命令行参数:--spring.profiles.active=prod。
环境变量:export SPRING_PROFILES_ACTIVE=sit。
3. 加载逻辑
当激活dev环境时,Spring Boot 会先加载application.properties中的公共配置,再加载application-dev.properties中的环境特定配置,后者会覆盖前者的同名配置。
若未激活任何环境,默认加载application.properties。
四、配置文件的加载流程源码解析
Spring Boot 的配置加载核心逻辑集中在SpringApplication类的prepareEnvironment()方法
简化流程如下:
1.创建基础环境:
初始化StandardServletEnvironment(Web 项目)或StandardEnvironment(非 Web 项目)。
注册系统属性(System.getProperties())和环境变量(System.getenv())。
2.加载应用配置文件:
通过SpringApplicationRunListeners监听配置加载事件。
使用ConfigFileApplicationListener从指定位置加载application.properties及其环境变体。
3.合并配置:
将命令行参数、环境变量等配置合并到Environment中,高优先级配置覆盖低优先级。
4.暴露配置:
通过ConfigurableApplicationContext将Environment暴露给应用,供@Value、@ConfigurationProperties等注解使用。
五、实践技巧与常见问题
1. 配置冲突排查
若发现配置未生效,可通过以下方式排查:
a.在日志中添加@Value("${server.port}") private String port;,启动时查看日志输出值。
b.使用SpringApplication的printBanner()方法打印有效配置:
public static void main(String[] args) {
new SpringApplication(MyApp.class).printBanner(System.out);
SpringApplication.run(MyApp.class, args);
}
2. 动态刷新配置
结合 Spring Boot Actuator 的/refresh端点,支持在不重启应用的情况下更新配置(需配合@RefreshScope注解):
添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
在配置类或属性类上添加@RefreshScope。
发送 POST 请求到/actuator/refresh触发配置刷新。
3. 自定义配置位置
通过spring.config.location参数指定额外的配置文件路径(优先级高于默认路径):
java -jar app.jar --spring.config.location=classpath:/custom/,file:/data/config/
六、Maven插件指定读取位置
前提:maven中配置profiles,如下,声明三个环境
<profiles>
<profile>
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
<final.name.suffix/>
</properties>
</profile>
<profile>
<id>sit</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profiles.active>sit</profiles.active>
<final.name.suffix/>
</properties>
</profile>
<profile>
<id>uat</id>
<properties>
<profiles.active>uat</profiles.active>
<final.name.suffix/>
</properties>
</profile>
</profiles>
在 Maven 中,
${profiles.active}
变量的值取决于当前激活的配置文件(Profile),Maven 有多种方式来决定激活哪个配置文件,以下为详细介绍:1. 默认激活配置文件
在
profiles
中,可以通过<activeByDefault>true</activeByDefault>
将某个配置文件设置为默认激活。例如上边给出的配置,在这个配置里,sit
配置文件被设置为默认激活,那么当你直接执行 Maven 命令时,${profiles.active}
的值就是sit
。2. 通过命令行参数激活配置文件
你可以在执行 Maven 命令时,使用
-P
参数来指定要激活的配置文件。例如:mvn clean install -P dev
这里的
-P dev
表示激活id
为dev
的配置文件,此时profiles.active
属性的值就会是dev
,并且在maven-resources-plugin
配置中${profiles.active}
会被替换为dev
,即复制../../profiles/black-manage/dev
目录下的资源文件。3. 根据环境变量或系统属性激活
可以在
profiles
的<activation>
标签中设置激活条件,根据环境变量或系统属性来决定激活哪个配置文件。示例如下:<profiles> <profile> <id>dev</id> <activation> <property> <name>env</name> <value>dev</value> </property> </activation> <properties> <profiles.active>dev</profiles.active> <final.name.suffix/> </properties> </profile> <!-- 其他配置文件 --> </profiles>
当你在执行 Maven 命令时设置了系统属性
env=dev
,如下所示:mvn clean install -Denv=dev
那么
dev
配置文件就会被激活,${profiles.active}
的值也会是dev
。4. 根据文件是否存在激活
还可以根据特定文件是否存在来激活配置文件,示例如下:
<profile> <id>dev</id> <activation> <file> <exists>src/main/resources/dev.properties</exists> </file> </activation> <properties> <profiles.active>dev</profiles.active> <final.name.suffix/> </properties> </profile>
如果
src/main/resources/dev.properties
文件存在,那么dev
配置文件就会被激活。5.编译时指定
profiles
通过上述这些方式,Maven 就能确定当前激活的配置文件,进而确定
${profiles.active}
的值。
6.通过profiles.active指定配置文件读取位置
确定
${profiles.active}
的值后,通过插件配置就能在项目在不同环境运行时,读取不同环境对应的配置文件,以下为maven插件配置配置文件路径:../../profiles/black-manage/${profiles.active}
其中,${profiles.active}的值为以上5种乃至更多方式获取而来。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<encoding>UTF-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration>
<executions>
<execution>
<id>copy-resources</id>
<phase>compile</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.build.outputDirectory} </outputDirectory>
<resources>
<resource>
<directory>../../profiles/black-manage/${profiles.active}</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
注意:一定保证项目路径下的配置文件后缀与多环境配置文件后缀一致,都为yml或都为properties,否则会多次加载,导致特定环境配置被覆盖!!!
七、总结
Spring Boot 的配置文件加载机制通过多层级优先级、多环境支持和灵活的扩展点,为开发者提供了强大的配置管理能力。理解其核心原理(如加载顺序、环境激活、配置合并)有助于在开发中避免配置冲突,实现不同环境的高效部署。在实际项目中,建议遵循 “公共配置放主文件,环境特定配置放 Profile 文件” 的原则,并结合命令行参数和环境变量实现动态配置,提升项目的可维护性与灵活性。