配置中心@ConfigurationProperties+@RefreshScope 动态配置

Posted go大鸡腿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了配置中心@ConfigurationProperties+@RefreshScope 动态配置相关的知识,希望对你有一定的参考价值。

前言

在之前写了一篇

本质就是缓存实例以及field,还有@Value的key,然后有变动的时候去刷新field

开发中会遇到@ConfigurationProperties去拿配置,如果按照上一篇去刷新,有点困难的,因为类里面的属性并不是每个都是拿配置的。

实现方案

@ConfigurationProperties+@RefreshScope 动态配置

  1. 写动态配置类
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
@Component
public class TestConfig {

    @Resource
    public TestCinfig2 cinfig2;

}
  1. application.yml配置项
com:
  a: test
@Data
@Component
@ConfigurationProperties(prefix = "com")
public class TestCinfig2 {

    private String a;

}
  1. 刷新spring environment
@Autowired
    private ConfigurableEnvironment environment;

    public void a(){
       
        Iterator<PropertySource<?>> iterator = environment.getPropertySources().iterator();
        while (iterator.hasNext()){
            PropertySource propertySources = iterator.next();
            System.out.println(propertySources.getName()+" "+propertySources.getSource());
        }
        environment.getPropertySources().remove("com.a");
        environment.getPropertySources().addFirst((new PropertySource<String>("com.a", "refresh") {
            // 重点
            @Override
            public Object getProperty(String s) {
                if (s.equals("com.a")) {//
                    return source;// 返回构造方法中的 source : refresh
                }
                return null;
            }
        }));
        System.out.println("------------------------------------------");
        Iterator<PropertySource<?>> iterator1 = environment.getPropertySources().iterator();
        while (iterator1.hasNext()){
            PropertySource propertySources = iterator1.next();
            System.out.println(propertySources.getName()+" "+propertySources.getSource());
        }
    }

重点:在ops推送的时候将key “com.a” ,value塞到“refresh”这一块

environment.getPropertySources().remove("com.a");
environment.getPropertySources().addFirst((new PropertySource<String>("com.a", "refresh") {
            // 重点
            @Override
            public Object getProperty(String s) {
                if (s.equals("com.a")) {//
                    return source;// 返回构造方法中的 source : refresh
                }
                return null;
            }
        }));
  1. 运行程序
public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(ConfigServer.class, args);
        //System.out.println(context.getBean(TestConfig.class).port);
        System.out.println(context.getBean(TestConfig.class).cinfig2.getA());
        context.getBean(TestConfig.class).a();
        context.getBean(ContextRefresher.class).refresh();
        //System.out.println(context.getBean(TestConfig.class).port);
        System.out.println(context.getBean(TestConfig.class).cinfig2.getA());
    }

原理

ConfigurableEnvironment去操作spring配置,然后通过@RefreshScope 在getBean的时候去刷新代理类,重新拿到值,促发机制ContextRefresher.refresh()或者Environment change Listener

以上是关于配置中心@ConfigurationProperties+@RefreshScope 动态配置的主要内容,如果未能解决你的问题,请参考以下文章

springboot给你一份Spring Boot知识清单

配置中心Config

Dubbo的多注册中心配置

Consule作为注册中心配置实例

Nacos配置中心(读取配置中心配置文件)

Apollo配置中心 原理分析