当前位置: 代码网 > it编程>编程语言>Asp.net > apollo动态刷新ConfigurationProperties注解标注的配置类方式

apollo动态刷新ConfigurationProperties注解标注的配置类方式

2025年12月02日 Asp.net 我要评论
apollo动态刷新configurationproperties注解标注的配置类默认情况下 apollo无法刷新 configurationproperties标注的属性实时更新我查看官方文档他推荐

apollo动态刷新configurationproperties注解标注的配置类

默认情况下 apollo无法刷新 configurationproperties标注的属性实时更新

我查看官方文档他推荐了两种实现思路

@refrashscope和通过environmentchangeevent

这两个都是在spring-cloud-context中提供的

我简单举个例子

/**
 * @description
 * @author changyandong
 * @emoji (゜ - ゜)つ干杯
 * @created date: 2019/11/20 9:01
 * @classname msgatewayproperties
 * @version: 1.0
 */
@component
@configurationproperties("ms.gateway")
public class msgatewayproperties {
    private msgatewayurlproperties url = new msgatewayurlproperties();

    public msgatewayurlproperties geturl() {
        return url;
    }

    public void seturl(msgatewayurlproperties url) {
        this.url = url;
    }
}
/**
 * @description
 * @author changyandong
 * @emoji (゜ - ゜)つ干杯
 * @created date: 2019/11/20 9:02
 * @classname msgatewayurlproperties
 * @version: 1.0
 */
public class msgatewayurlproperties {
    private string sss;
    private string xxx;

    public string getsss() {
        return sss;
    }

    public void setsss(string sss) {
        this.sss = sss;
    }

    public string getxxx() {
        return xxx;
    }

    public void setxxx(string xxx) {
        this.xxx = xxx;
    }
}

然后我创建一个apollo监听类 这里的configchangeservice是我们框架封装的

如果自己写的话一个普通的@apolloconfigchangelistener类即可

/**
 * @description
 * @author changyandong
 * @emoji (゜ - ゜)つ干杯
 * @created date: 2019/11/20 9:00
 * @classname msgatewayappollochangeserivce
 * @version: 1.0
 */
@component
public class msgatewayapollochangeservice implements configchangeservice, applicationcontextaware {

    private logger logger = loggerfactory.getlogger(msgatewayapollochangeservice.class);

    private applicationcontext applicationcontext;

    @override
    public void detectconfigchanges(configchangeevent changeevent) {
        boolean gatewaypropertieschanged = false;

        for (string changedkey : changeevent.changedkeys()) {

            //前缀为spring.cloud.gateway的key发生了改变(gateway的配置发生了改变)
            if (changedkey.startswith("ms.gateway")) {
                gatewaypropertieschanged = true;
                break;
            }
        }

        //更新gateway配置
        if (gatewaypropertieschanged) {
            refreshgatewayproperties(changeevent);
        }

    }

    /**
     * 更新springapplicationcontext对象,并更新路由
     *
     * @param changeevent
     */
    private void refreshgatewayproperties(configchangeevent changeevent) {
        //更新配置
        this.applicationcontext.publishevent(new environmentchangeevent(changeevent.changedkeys()));
    }


    @override
    public int getorder() {
        return 1;
    }

    @override
    public void setapplicationcontext(applicationcontext applicationcontext) throws beansexception {
        this.applicationcontext = applicationcontext;
    }
}

这时他给spring推了一个事件 environmentchangeevent

这时会触发configurationpropertiesrebinder的onapplicationevent方法进而触发rebind方法

@component
@managedresource
public class configurationpropertiesrebinder
  implements applicationcontextaware, applicationlistener<environmentchangeevent> {

 private configurationpropertiesbeans beans;

 private applicationcontext applicationcontext;

 private map<string, exception> errors = new concurrenthashmap<>();

 public configurationpropertiesrebinder(configurationpropertiesbeans beans) {
  this.beans = beans;
 }

 @override
 public void setapplicationcontext(applicationcontext applicationcontext)
   throws beansexception {
  this.applicationcontext = applicationcontext;
 }

 /**
  * a map of bean name to errors when instantiating the bean.
  * @return the errors accumulated since the latest destroy.
  */
 public map<string, exception> geterrors() {
  return this.errors;
 }

 @managedoperation
 public void rebind() {
  this.errors.clear();
  // 这里会把标注了configurationproperties的所有类都扫一遍
  for (string name : this.beans.getbeannames()) {
   rebind(name);
  }
 }

 @managedoperation
 public boolean rebind(string name) {
  if (!this.beans.getbeannames().contains(name)) {
   return false;
  }
  // 这里他把对象 销毁再创建  但是由于我只想刷新我自己的类 这里却把所有带configurationproperties注解的都销毁重新创建 
  // 这样就很难以让我们采用这种方式
  if (this.applicationcontext != null) {
   try {
    object bean = this.applicationcontext.getbean(name);
    if (aoputils.isaopproxy(bean)) {
     bean = proxyutils.gettargetobject(bean);
    }
    if (bean != null) {
     this.applicationcontext.getautowirecapablebeanfactory()
       .destroybean(bean);
     this.applicationcontext.getautowirecapablebeanfactory()
       .initializebean(bean, name);
     return true;
    }
   }
   catch (runtimeexception e) {
    this.errors.put(name, e);
    throw e;
   }
   catch (exception e) {
    this.errors.put(name, e);
    throw new illegalstateexception("cannot rebind to " + name, e);
   }
  }
  return false;
 }

 @managedattribute
 public set<string> getbeannames() {
  return new hashset<>(this.beans.getbeannames());
 }

 @override
 public void onapplicationevent(environmentchangeevent event) {
  if (this.applicationcontext.equals(event.getsource())
    // backwards compatible
    || event.getkeys().equals(event.getsource())) {
   rebind();
  }
 }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com