spring加载外部properties文件属性时,读取到userName变量值和properties文件的值不一致

问题

使用spring DI注入外部properties文件属性时,读取到userName变量值和properties文件的值不一致。

bean属性注入:

java 复制代码
 <!--加载配置文件-->
<context:property-placeholder location="classpath:*.properties"/>

<bean id="userDao" class="com.fjd.dao.impl.UserDaoImpl">
        <property name="userName" value="${userName}"/>
        <property name="password" value="${password}"/>
</bean>

properties文件内容:

输出结果:

原因分析

问题的根源在于:系统环境变量与属性文件中的变量名冲突。在Spring 中,${} 占位符会按特定顺序解析属性源,而系统环境变量优先级高于 properties 文件。

  • 冲突的变量名:
    • userName 是常见系统环境变量(存储当前登录用户名)
    • properties 文件也定义了同名变量
  • Spring 属性解析顺序:
    • 当使用 ${userName} 时,Spring 按此顺序查找:
  1. JVM 系统属性 (-D 参数)
  2. 操作系统环境变量 👉 这里找到了系统用户名!
  3. properties 文件中的属性

解决方法

方案 1:重命名属性(推荐)
  • 修改 properties 文件,添加前缀避免冲突:
java 复制代码
# 修改后
db.userName=root
db.password=123
  • 修改 Spring 配置:
java 复制代码
<bean id="userDao" class="com.fjd.dao.impl.UserDaoImpl">
    <property name="userName" value="${db.userName}"/>
    <property name="password" value="${db.password}"/>
</bean>
方案 2:调整属性源优先级(Spring 4.3+)

在 PropertySourcesPlaceholderConfigurer 中显式设置优先级:

java 复制代码
<bean  <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath*:data.properties</value>
            </list>
        </property>
        <!-- 关键:让本地属性覆盖系统环境变量 -->
        <property name="localOverride" value="true"/>
    </bean>

注意:确保上述bean是在applicationContext.xml文件中第一个定义的bean

  • 为什么要作为第一个定义的bean(额外知识点!)
    1.Spring 容器初始化顺序

    2.关键机制解析
java 复制代码
BeanFactoryPostProcessor 的特殊性:
PropertySourcesPlaceholderConfigurer实现了BeanFactoryPostProcessor 接口
后置处理器优先:BeanFactoryPostProcessor 必须先于普通 bean
这类 bean 会在普通 bean 实例化之前执行
但多个 BeanFactoryPostProcessor 之间仍有执行顺序

3.工作流程

java 复制代码
Spring 首先初始化 PropertySourcesPlaceholderConfigurer
它立即加载 data.properties 并注册到环境
设置 localOverride=true 使这些属性覆盖系统环境变量
当初始化 userDao 时,${userName} 已使用文件中的值

4.位置决定执行顺序:

bash 复制代码
XML中先定义的BeanFactoryPostProcessor先执行,如果放在后面,
可能其他处理器已修改了环境