当前位置: 首页 > news >正文

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

问题

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

 <!--加载配置文件-->
<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 文件,添加前缀避免冲突:
# 修改后
db.userName=root
db.password=123
  • 修改 Spring 配置:
<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 中显式设置优先级:

<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.关键机制解析
BeanFactoryPostProcessor 的特殊性:
PropertySourcesPlaceholderConfigurer实现了BeanFactoryPostProcessor 接口
后置处理器优先:BeanFactoryPostProcessor 必须先于普通 bean
这类 bean 会在普通 bean 实例化之前执行
但多个 BeanFactoryPostProcessor 之间仍有执行顺序

        3.工作流程

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

        4.位置决定执行顺序:

XML中先定义的BeanFactoryPostProcessor先执行,如果放在后面,
可能其他处理器已修改了环境
http://www.lryc.cn/news/580379.html

相关文章:

  • 动手实践OpenHands系列学习笔记8:后端服务开发
  • 大数据在UI前端的应用探索:基于用户行为分析的产品优化策略
  • [论文阅读] 软件工程 | 可持续性标志在问答平台中的应用
  • 基于matlab卡尔曼滤波器消除噪声
  • [前缀和+多重背包]3333. 找到初始输入字符串 II
  • JMM--数据原子操作
  • 【深圳大学机器学习】实验一:PCA算法
  • Qt窗口被外部(非Qt内部机制)强制销毁,第二次再重复使用不显示
  • cloudflare配合github搭建免费开源影视LibreTV一个独享视频网站 详细教程
  • vue3 el-input el-select 非空校验
  • 每日学习问题记录
  • DVWA靶场通关笔记-验证码绕过reCAPTCHA(High级别)
  • vue中添加原生右键菜单
  • 【零基础学AI】第24讲:卷积神经网络(CNN)架构设计
  • 【无标题】Go语言中的反射机制 — 元编程技巧与注意事项
  • 3dmax物理材质转换标准材质,物理材质转VR材质,VR材质转标准材质3dmax物理材质转标准材质插件
  • 电脑休眠设置
  • c++ python 共享内存
  • 后端树形结构
  • STM32F103RCTx的PWM输出控制电机
  • js游戏简单修改
  • React Native 开发环境搭建--mac--android--奔溃的一天
  • Hinge×亚矩云手机:以“深度连接”为名,重构云端社交的“真实感”
  • CSS02:四种CSS导入方式
  • pyspark大规模数据加解密优化实践
  • Python小工具之PDF合并
  • 数据结构:多维数组在内存中的映射(Address Mapping of Multi-dimensional Arrays)
  • IDEA中application.yml配置文件不自动提示解决办法
  • 如何在IntelliJ IDEA中设置数据库连接全局共享
  • 从“电话催维修“到“手机看进度“——售后服务系统开发如何重构客户体验