configurableenvironment 不支持运行期直接修改已加载配置,但可通过动态添加高优先级 propertysource 实现覆盖;推荐用 addfirst() 插入 mappropertysource,并配合 @refreshscope 或 refreshable=true 与 contextrefresher 实现热刷新。

ConfigurableEnvironment 本身不支持在运行期直接“修改”已加载的配置源(比如 application.yml 中的值),它主要用于启动阶段的环境初始化和配置源(PropertySource)的注册。但你可以通过向其 PropertySources 中动态添加新的、高优先级的 PropertySource,实现“覆盖”效果——这在 Spring Boot 应用中是常见且安全的做法。
理解优先级:后添加的 PropertySource 优先级更高
Spring 的 Environment 会按 PropertySource 的顺序查找属性,越靠后的 Source 优先级越高。ConfigurableEnvironment 提供了 getPropertySources().addFirst() 或 addLast() 方法,推荐用 addFirst() 确保你的动态配置能覆盖原有值。
-
addFirst(ps):新 PropertySource 排在最前面,生效最快 -
addLast(ps):排在末尾,通常不会覆盖已有配置 - 注意:不能删除或修改已存在的 PropertySource,只能新增
手动注入 ConfigurableEnvironment 并添加 MapPropertySource
在任意 Spring 管理的 Bean(如 @Service、@Component)中,注入 ConfigurableEnvironment,然后构造一个基于 Map 的 PropertySource:
@Autowired
private ConfigurableEnvironment environment;
public void updateRuntimeProperty(String key, String value) {
MutablePropertySources propertySources = environment.getPropertySources();
// 先移除同名旧 source(可选,避免重复)
propertySources.remove("runtime-dynamic");
// 创建新 source
Map<string object> map = new HashMap();
map.put(key, value);
MapPropertySource dynamicSource = new MapPropertySource("runtime-dynamic", map);
// 插入到最前
propertySources.addFirst(dynamicSource);
}</string>
配合 @ConfigurationProperties 实现实时刷新(需额外支持)
单纯加 PropertySource 不会让已注入的 @ConfigurationProperties 对象自动更新。若需“热刷新”,需满足以下条件:
- 目标类使用
@RefreshScope(Spring Cloud Context)——适用于微服务场景 - 或使用
@ConfigurationProperties(refreshable = true)(Spring Boot 3.3+ 支持) - 调用
ContextRefresher.refresh()触发重新绑定(Spring Boot 2.x/3.x 均支持)
示例(需引入 spring-boot-starter-actuator):
@Autowired
private ContextRefresher contextRefresher;
public void refreshAndApply(String key, String value) {
updateRuntimeProperty(key, value);
contextRefresher.refresh(); // 重新绑定 @ConfigurationProperties 和 @Value
注意事项与限制
动态配置不是万能的,要注意这些边界:
-
@Value("${xxx}")是启动时解析的,除非所在 Bean 是@RefreshScope,否则不会更新 - 原生类型(如 int、boolean)在注入后不会自动转换,建议统一用 String 接收再解析
- 多线程并发修改时,
MutablePropertySources非线程安全,建议加锁或用 CopyOnWriteArrayList 包装(Spring 内部未做同步) - 生产环境慎用,建议配合权限校验、审计日志和配置回滚机制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











