We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
问题描述: 当使用 SpringCloud 并且未主动关闭 BootstrapApplicationListener 时,如果动态调整配置,新增和删除 key 无法正确映射到绑定属性上
问题原因: SpringCloud 项目启动时 BootstrapApplicationListener 会在 applicationContext 创建之前先创建一个 bootstrapApplicationContext,用来优先加载环境变量,这会出现两次容器加载,触发两次 ApolloApplicationContextInitializer 初始化 当触发两次 ApolloApplicationContextInitializer 初始化时 CachedCompositePropertySource 缓存的 propertyNames 会因监听器问题无法刷新
代码说明:
// ApolloApplicationContextInitializer::initialize CompositePropertySource composite; if (configUtil.isPropertyNamesCacheEnabled()) { // 此处每次都会创建一个新的 CachedCompositePropertySource ,但是 name 相同 composite = new CachedCompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); } else { composite = new CompositePropertySource(PropertySourcesConstants.APOLLO_BOOTSTRAP_PROPERTY_SOURCE_NAME); } for (String namespace : namespaceList) { Config config = ConfigService.getConfig(namespace); composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config)); }
// AbstractConfig::addChangeListener @Override public void addChangeListener(ConfigChangeListener listener, Set<String> interestedKeys, Set<String> interestedKeyPrefixes) { /* 此处根据 PropertySource 名称判断,由于 bootstrapApplicationContext 中已经设置过一次 * applicationContext 创建时新 new 对象 CachedCompositePropertySource 无法设置到监听里面 * 进而导致监听器中的保存的一直是旧的 CachedCompositePropertySource,而 applicationContext 实际使用新的 */ if (!m_listeners.contains(listener)) { m_listeners.add(listener); if (interestedKeys != null && !interestedKeys.isEmpty()) { m_interestedKeys.put(listener, Sets.newHashSet(interestedKeys)); } if (interestedKeyPrefixes != null && !interestedKeyPrefixes.isEmpty()) { m_interestedKeyPrefixes.put(listener, Sets.newHashSet(interestedKeyPrefixes)); } } }
public class CachedCompositePropertySource extends CompositePropertySource implements ConfigChangeListener { private volatile String[] names; public CachedCompositePropertySource(String name) { super(name); } @Override public String[] getPropertyNames() { // 无法触发监听器,缓存仍然是所有旧 key,而 SpringBoot 属性绑定会使用这个方法 String[] propertyNames = this.names; if (propertyNames == null) { this.names = propertyNames = super.getPropertyNames(); } return propertyNames; } @Override public void onChange(ConfigChangeEvent changeEvent) { // 正常情况下应该触发监听器,让 names 置空,从而触发调用时刷新 // 此处 applicationContext 中 CachedCompositePropertySource 无法触发 this.names = null; } }
The text was updated successfully, but these errors were encountered:
Sorry, something went wrong.
No branches or pull requests
问题描述:
当使用 SpringCloud 并且未主动关闭 BootstrapApplicationListener 时,如果动态调整配置,新增和删除 key 无法正确映射到绑定属性上
问题原因:
SpringCloud 项目启动时 BootstrapApplicationListener 会在 applicationContext 创建之前先创建一个 bootstrapApplicationContext,用来优先加载环境变量,这会出现两次容器加载,触发两次 ApolloApplicationContextInitializer 初始化
当触发两次 ApolloApplicationContextInitializer 初始化时 CachedCompositePropertySource 缓存的 propertyNames 会因监听器问题无法刷新
代码说明:
The text was updated successfully, but these errors were encountered: