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();
}
}
}



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