Apollo修改配置文件后运行中的项目使用@ConfigurationProperties的配置实时更新

问题:

apollo动态刷新,应用在@value这种注入方式的属性没有问题,但是如果使用@ConfigurationProperties注解的bean,动态刷新就不好使了,会注入不到的。

解决方法:

方式1:

新建一个监听类。

/**
 * Apollo配置监听
 *
 * @date 2022/9/6 15:16
 */
@Configuration
@Slf4j
public class ApolloChangeListener implements ApplicationContextAware
{
    @Autowired
    private ApplicationContext applicationContext;
    
    @ApolloConfigChangeListener()
    public void refresh(ConfigChangeEvent changeEvent) {
        log.info("Apollo配置发生了变化");
        for(String changedKey : changeEvent.changedKeys())
        {
            log.info(changeEvent.changedKeys().toString()+" before refresh:{}",changeEvent.getChange(changedKey).getOldValue());
            log.info(changeEvent.changedKeys().toString()+" after refresh:{}",changeEvent.getChange(changedKey).getNewValue());
        }
        // 刷新的bean
        applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
        //相关业务处理

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
    {
        this.applicationContext = applicationContext;
    }
}

方式2:

被@ConfigurationProperties修饰的类需要添加如下注解:

@Component
@RefreshScope

新建一个监听类。

/**
 * Apollo配置监听
 *
 * @date 2022/9/6 15:16
 */
@Configuration
@Slf4j
public class ApolloChangeListener
{
    @Autowired
    private RefreshScope refreshScope;
    
    @ApolloConfigChangeListener()
    public void refresh(ConfigChangeEvent changeEvent) {
        log.info("Apollo配置发生了变化");
        for(String changedKey : changeEvent.changedKeys())
        {
            log.info(changeEvent.changedKeys().toString()+" before refresh:{}",changeEvent.getChange(changedKey).getOldValue());
            log.info(changeEvent.changedKeys().toString()+" after refresh:{}",changeEvent.getChange(changedKey).getNewValue());
        }
        // 刷新的bean
        refreshScope.refreshAll();
        //刷新指定的
        //refreshScope.refresh("myConfig");
        //相关业务处理

    }
}

说明:
@ApolloConfigChangeListener()注解中可填写参数
interestedKeyPrefixes:指定监听的配置属性前缀。当在Apollo配置中心修改配置,配置发生变化的前缀是所填值,那么就执行带有@ApolloConfigChangeListener()注解方法
value:指定监听的配置文件。
注:如果不填写属性值,默认是只要发生变化都执行方法
例子:@ApolloConfigChangeListener(value = "application.yml", interestedKeyPrefixes = "my.config.")
例子说明:当在Apollo配置中心,修改application.yml下的,前缀为my.config的属性时,触发刷新方法执行。

额外说明:

有时候,动态刷新成功后,发现有些调用相关接口执行还是原配置的效果,没成功(比如某个花钱的配置属性的环境切换,pro改为test,调用相关接口发现执行时属性还是pro时的效果)。
那有可能是因为涉及到配置类启动时初始化的问题,比如说,有个注入到spring容器的配置类(@Configuration@bean)刚好用到你这个带有@ConfigurationProperties类在项目启动进行初始化。项目启动后,已经注入到了spring容器中,你动态刷新的配置属性值,但是没有去把容器中的这个配置类再次刷新,那么配置类还是原来的配置类,里面的属性也还是原来的。
解决方法:在上面//相关业务处理下面,也就是配置动态刷新后,再次初始化一下spring容器中的那个配置类,就能生效成功了。
(可能表达的不是很好。。。,说白了可能就是调用到相关配置属性另一个bean没有刷新)

参考:https://blog.csdn.net/luo15242208310/article/details/115521686

posted @ 2022-09-30 15:35  chandol  阅读(1881)  评论(0编辑  收藏  举报