问题描述: 最近在搭建Spring Cloud Alibaba 这一套架构。在阅读了些许博客后,开始操作。
- 我在start.aliyun.com上用阿里云的脚手架生成的nacos的应用,勾选了服务注册发现和动态配置两个依赖。
- 生成git代码后,clone到本地,删除了一些不必要的模块demo代码后。修改配置连接到我搭建的nacos,nacos采用的是单机启动,没有配置数据库或者Redis缓存等,重启就会丢失所有配置文件的那种。
- 修改完应用的相关配置后,启动并能成功注册到我搭建的nacos并能成功读取配置初始化我相关配置参数。
问题:启动成功后当我修改对应dataId的配置文件时,我能清楚的感知到修改后的配置并没有成功应用到我的应用里。
尝试过解决问题的方法:
- 代码debug,我能看到在跟读代码的时候,应用是获取到了最新的配置信息,但是在我实现的 InitializingBean 接口中,参数会被原来的值覆盖。
截图:
应用成功启动:
nacos配置:
nacos配置修改后:更改了user.name 和user.age两个参数
应用日志输出:
@Configuration
@EnableConfigurationProperties(User.class)
public class NacosConfigDemoConfiguration {
@Autowired
private NacosConfigManager nacosConfigManager;
@Autowired
private User user;
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private int userAge;
@Bean
public ApplicationRunner runner() {
return args -> {
String dataId = "SpringCloudDemo.properties";
String group = "DEFAULT_GROUP";
nacosConfigManager.getConfigService().addListener(dataId, group, new AbstractListener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("[Listener] " + configInfo);
System.out.println("[Before User] " + user);
Properties properties = new Properties();
try {
properties.load(new StringReader(configInfo));
String name = properties.getProperty("user.name");
int age = Integer.valueOf(properties.getProperty("user.age"));
user.setName(name);
user.setAge(age);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("[After User] " + user);
}
});
};
}
@PostConstruct
public void init() {
System.out.printf("[init] user name : %s , age : %d%n", userName, userAge);
}
@PreDestroy
public void destroy() {
System.out.printf("[destroy] user name : %s , age : %d%n", userName, userAge);
}
}
日志第一块部分 Listener 是这里的代码获取输出的
user配置类代码:
@RefreshScope
@ConfigurationProperties(prefix = "user")
public class User implements InitializingBean, DisposableBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[afterPropertiesSet()] " + toString());
}
@Override
public void destroy() throws Exception {
System.out.println("[destroy()] " + toString());
}
}
可以从日志中发现,配置其实是有通知到本地应用的,但是在user中,InitializingBean 这个接口重新生成的user相关的参数却是修改前的。
说明:NacosConfigDemoConfiguration#中的ApplicationRunner 这个bean之前没有启用,在user的afterPropertiesSet()和destroy()方法中无法明显的观测到动态配置未刷新的原因。在启用后会发现,其实修改后的配置是通知到了应用的,但是搞不懂为什么新的值会被原有的值覆盖。
排查后发现可能是版本问题,但是我用的阿里云原生的脚手架生成的,按理说不会出现cloud和boot的版本冲突。spring-boot-starter-parent切换了几个版本后排查后均会出现此问题: 这里贴一下使用的版本:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.0.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.0.4.0</version>
</dependency>
希望大佬能帮我解决一下问题。谢谢~