bigywater.tech
Spring · 11

Environment 与 PropertySource:属性解析顺序与占位符

属性从哪里读、谁覆盖谁?@Value 的占位符缺失时为什么有时报错有时不报?字符串怎么转布尔?中文配置为什么乱码?这篇在 Spring Framework 7.0.9 上逐项验证。

3 个
默认的 PropertySource 顺序:systemProperties、systemEnvironment、@PropertySource 文件
${missing.key}
没有 PropertySourcesPlaceholderConfigurer 时,缺失的 @Value 被注入的字面量
12 对 4
@PropertySource 读 UTF-8 的 title=中文标题,默认读法与 encoding=UTF-8 得到的字符数

优先级

实测 · 本机执行输出
  PropertySource 的顺序(先找前面的):[systemProperties, systemEnvironment, class path resource [app.properties]]
  app.name = from -D system property(系统属性、环境变量、app.properties 里都可能有)
  only.file = only in file;MY_NAME(环境变量)用 my.name 取 = 来自环境变量;用 MY_NAME 取 = 来自环境变量
  addFirst 一个 MapPropertySource 之后 app.name = 运行时 addFirst 加的
  再用 addLast 加一个同名键:app.name = from -D system property(addLast 排在最后,赢不了);late.only = 晚到的

系统属性在环境变量之前,@PropertySource 加载的文件排在后面;addFirst / addLast 控制新加的属性源在前还是在后。

占位符

实测 · 本机执行输出
  resolvePlaceholders("${nope}") = ${nope}(宽松,保持原样)
  resolveRequiredPlaceholders("${nope}") → PlaceholderResolutionException: Could not resolve placeholder 'nope' in value "${nope}"
  ${nope:默认} → 默认;${who} → spring;嵌套默认值 greeting → hello spring
  嵌套占位符:url=${url.${region}},region=cn → ${url} = https://cn.example

宽松解析保持原样,严格解析抛异常;支持默认值和嵌套。

@Value

实测 · 本机执行输出
  nopspc:@Value("${missing.key}") = [${missing.key}];带默认值的 = [默认值];@Value("${app.name}") = [from app.properties];SpEL #{systemProperties['user.language']} = [en]
  pspc:启动失败 PlaceholderResolutionException: Could not resolve placeholder 'missing.key' in value "${missing.key}"

没有 PropertySourcesPlaceholderConfigurer 时缺失键会被原样注入,有了才会启动失败。

类型转换

实测 · 本机执行输出
  字符串 → Boolean:{true=true, yes=true, on=true, 1=true, false=false, no=false, off=false, 0=false, TRUE=true, abc=ConversionFailedException}
  port 作为 Integer = 8080;不存在的键 getProperty("x", Integer.class) = null;带默认值 = 9090;getRequiredProperty 不存在的键 → IllegalStateException: Required key 'x' not found

yes、on、1 都被当作 true;转换不了抛 ConversionFailedException。

文件编码

实测 · 本机执行输出
  default:title = [中文标题] 字符数 12(期望“中文标题”4 个字符)
  utf8:title = [中文标题] 字符数 4(期望“中文标题”4 个字符)

@PropertySource 读 .properties 默认不是 UTF-8,中文要加 encoding。

文件不存在

实测 · 本机执行输出
  ignore:启动成功
  noignore:FileNotFoundException: class path resource [nope.properties] cannot be opened because it does not exist

默认启动失败,ignoreResourceNotFound = true 才会跳过。

分步演示

Environment 与 PropertySource
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / OpenJDK 21.0.12(Homebrew) / Spring Boot 4.0.8(Spring Framework 7.0.9、Tomcat 11.0.24) / Spring Cloud 2025.1.3;用 javac 编译、java 直接运行,依赖由 Maven 从 Maven Central 解析;数字每次运行会有小幅抖动。用不带 Boot 的 Spring Framework 7.0.9;环境变量 MY_NAME 是启动 JVM 时设的;第五节默认读法的乱码是 UTF-8 字节被当作单字节编码读出来的结果,具体是 ISO-8859-1 还是别的编码我没有逐字节核对
    • 没有验证:Boot 的 application.properties / application.yml 与 @PropertySource 的优先级(见后面的 Boot 篇);@PropertySource 支持 YAML 的做法;profile 专用的 @PropertySource 路径写法;PropertySource 的刷新(见 Cloud 篇的 @RefreshScope);Windows 环境变量不区分大小写的映射
    京ICP备2026067502号-1京公网安备11010502063487号