spring @Value 注解更新的实现

SpringBoot 的 @Value 注解本身并不支持动态更新,但如果你结合了 @RefreshScope (context)和配置更新机制(nacos, spring cloud config) 可实现动态更新。

spring cloud context 4.3.0

一、核心机制

1. 标记了 @RefreshScope 注解

    标记了 @RefreshScope 的Bean 会被特殊处理,当配置更新时。(不重启应用), 这些Bean 会被销毁,下次访问时重新创建,然后再引用新的配置值。

2、更新触发

发送HTTP post 请求到/actuator/refresh 请求,触发更新事件。

如: curl -X POST http://localhost:7082/actuator/refresh

二、具体步骤如下:

1. pom 依赖.

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>4.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2. 配置RefreshScope 注解

@RefreshScope // 启用动态刷新
@RestController
public class DynamicTestController {

    @Value("${dynamic.property:default}") 
    private String myDynamicProperty;

    @GetMapping("/property")
    public String getProperty() {
        return myDynamicProperty;
    }
}

3. 开启刷新配置application.yml

management:
  endpoints:
    web:
      exposure:
        include: health,refresh,info


dynamic:
  property: default

4、发送请求更新

不重启应用,修改配置:

dynamic:
  property: world2

curl -X POST http://localhost:7082/actuator/refresh

5、查看更新后的配置:

三、调用过程解析

1、Refresh endpoint 刷洗 代码

@Endpoint(id = "refresh")
public class RefreshEndpoint {

	private static final Log LOG = LogFactory.getLog(RefreshEndpoint.class);

	private final ContextRefresher contextRefresher;

	public RefreshEndpoint(ContextRefresher contextRefresher) {
		this.contextRefresher = contextRefresher;
	}

	@WriteOperation
	public Collection<String> refresh() {
		Set<String> keys = this.contextRefresher.refresh();
		LOG.info("Refreshed keys : " + keys);
		return keys;
	}

}

public abstract class ContextRefresher {

	public synchronized Set<String> refresh() {
		Set<String> keys = refreshEnvironment();
		this.scope.refreshAll();
		return keys;
	}
}

2、Refresh 图解

refresh 刷新序列图

3、说明

  • RefreshEndpoint.refresh()

    • 入口:处理 /actuator/refresh 请求

    • 调用 ContextRefresher.refresh()

  • ContextRefresher.refresh()

    • 更新环境:updateEnvironment() 重新加载配置源(如PropertySource

    • 销毁Bean:调用 RefreshScope.refreshAll()

  • RefreshScope.refreshAll()

    • 清除缓存:super.destroy() 销毁所有@RefreshScope Bean

    • 发送销毁事件:RefreshScopeRefreshedEvent,

  • Bean重建流程

    • 下次访问Controller时,Spring重新创建Bean

    • Bean创建时调用 AutowiredAnnotationBeanPostProcessor 处理 @Value

    • @Value 通过 PropertySourcesPlaceholderConfigurer 从 Environment 解析新值,更新后的 Environment 中读取新值

四、汇总

Refresh 刷新步骤
步骤组件功能
1@RefreshScope标记需动态刷新的Bean
2/actuator/refresh触发配置更新
3ContextRefresher更新环境并销毁Bean,发送事件更新消息
4Bean重建@Value 重新注入新值

 注意:

  • 刷新会销毁并重建Bean,频繁更新可能影响性能。(可以借助Nacos 配置, 降低影响)

  • 仅对 @RefreshScope Bean有效,普通Bean不会更新。

  • 动态配置源需支持实时更新(如Nacos, Spring Cloud Config、Consul等)。

  • 更新期间访问Bean可能短暂不可用,需确保客户端重试机制。

  • 安全性,建议开启endpoint 的refresh 时,添加认证机制。或者借助Nacos 等配置中心进行动态配置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nextera-void

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值