高级开发 | 零人工干预的 @Value 实时刷新
高级开发 | 零人工干预的 @Value 实时刷新
目标:运行时把 最新配置 写进
Environment
→ 自动广播事件 → 所有带@Value
的 Bean 毫秒级重注入,零人工干预。
1. 整体思路
- 动态 PropertySource 始终指向最新配置。
- Spring 事件总线 在配置变更时自动触发。
- 统一重注入器 监听事件,批量刷新所有
@Value
字段。
2. 代码实现(可直接拷贝)
2.1 动态 PropertySource(实时数据源)
@Component
public final class DynamicPropertyHolder extends PropertySource<Object> {private final AtomicReference<Map<String, Object>> store = new AtomicReference<>(Map.of());public DynamicPropertyHolder() {super("dynamic");}@Overridepublic Object getProperty(String name) {return store.get().get(name);}/** 发布配置变更事件 */public void publish(Map<String, Object> newMap) {Map<String, Object> old = store.getAndSet(newMap);if (!Objects.equals(old, newMap)) {SpringUtil.publishEvent(new ConfigRefreshedEvent());}}
}
2.2 自动注册到 Environment(最高优先级)
@Component
public class DynamicPropertyRegistrar implements EnvironmentAware {private ConfigurableEnvironment env;@Overridepublic void setEnvironment(Environment environment) {this.env = (ConfigurableEnvironment) environment;env.getPropertySources().addFirst(SpringUtil.getBean(DynamicPropertyHolder.class));}
}
2.3 统一重注入器(监听事件,自动刷新)
@Component
public class ValueAutoRefresher implements ApplicationListener<ConfigRefreshedEvent> {private final ConfigurableListableBeanFactory factory;public ValueAutoRefresher(ConfigurableListableBeanFactory factory) {this.factory = factory;}@Overridepublic void onApplicationEvent(ConfigRefreshedEvent event) {String[] names = factory.getBeanDefinitionNames();for (String name : names) {Object bean = factory.getBean(name);ReflectionUtils.doWithFields(bean.getClass(), field -> {if (field.isAnnotationPresent(Value.class)) {field.setAccessible(true);String spel = field.getAnnotation(Value.class).value();String key = spel.replaceAll("\\$\\{([^:]+?)(:.*)?}", "$1");Object val = factory.resolveEmbeddedValue("${" + key + "}");ReflectionUtils.setField(field, bean, val);}});}}
}
3. 触发方式(零人工)
任何线程只要把最新配置塞进 DynamicPropertyHolder
即可:
@Autowired DynamicPropertyHolder holder;public void updateConfig() {holder.publish(Map.of("sms.apiKey", "newKey123","sms.timeout", 3000));
}
- holder.publish(…) 自动写 Environment
- ConfigRefreshedEvent 自动广播
- ValueAutoRefresher 自动重注入所有
@Value
4. 避坑 & 性能
点 | 说明 |
---|---|
构造器注入 | 不支持刷新,改用字段/Setter |
并发安全 | AtomicReference + 事件总线无锁 |
刷新粒度 | 只扫描带 @Value 的 Bean,O(N) ≈ 毫秒级 |
5. 一句话总结
最新配置 → DynamicPropertyHolder → 事件总线 → 自动刷新所有
@Value
全程 零人工干预,Spring 原生能力即可实现 毫秒级热更新。