diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigAutoConfiguration.java
index b82a2ddcf..3976a7d01 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigAutoConfiguration.java
@@ -20,7 +20,9 @@ package com.tencent.cloud.polaris.config;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceAutoRefresher;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
+import com.tencent.cloud.polaris.config.adapter.SmartConfigurationPropertiesRebinder;
import com.tencent.cloud.polaris.config.annotation.PolarisConfigAnnotationProcessor;
+import com.tencent.cloud.polaris.config.condition.ConditionalOnNonDefaultBehavior;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.config.listener.PolarisConfigChangeEventListener;
import com.tencent.cloud.polaris.config.spring.annotation.SpringValueProcessor;
@@ -28,7 +30,11 @@ import com.tencent.cloud.polaris.config.spring.property.PlaceholderHelper;
import com.tencent.cloud.polaris.config.spring.property.SpringValueRegistry;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.SearchStrategy;
+import org.springframework.cloud.context.properties.ConfigurationPropertiesBeans;
+import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -77,4 +83,14 @@ public class PolarisConfigAutoConfiguration {
return new SpringValueProcessor(placeholderHelper, springValueRegistry, polarisConfigProperties);
}
+ @Bean
+ @ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
+ @ConditionalOnNonDefaultBehavior
+ public ConfigurationPropertiesRebinder smartConfigurationPropertiesRebinder(
+ ConfigurationPropertiesBeans beans) {
+ // If using default behavior, not use SmartConfigurationPropertiesRebinder.
+ // Minimize te possibility of making mistakes.
+ return new SmartConfigurationPropertiesRebinder(beans);
+ }
+
}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java
index a67c8a89d..7c7afdf87 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/PolarisConfigBootstrapAutoConfiguration.java
@@ -19,6 +19,8 @@ package com.tencent.cloud.polaris.config;
import com.tencent.cloud.polaris.config.adapter.PolarisConfigFileLocator;
import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
+import com.tencent.cloud.polaris.config.adapter.SmartConfigurationPropertiesRebinder;
+import com.tencent.cloud.polaris.config.condition.ConditionalOnNonDefaultBehavior;
import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
import com.tencent.cloud.polaris.context.ConditionalOnPolarisEnabled;
import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration;
@@ -27,7 +29,11 @@ import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import com.tencent.polaris.configuration.factory.ConfigFileServiceFactory;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.condition.SearchStrategy;
+import org.springframework.cloud.context.properties.ConfigurationPropertiesBeans;
+import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -79,4 +85,14 @@ public class PolarisConfigBootstrapAutoConfiguration {
PolarisContextProperties polarisContextProperties) {
return new ConfigurationModifier(polarisConfigProperties, polarisContextProperties);
}
+
+ @Bean
+ @ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
+ @ConditionalOnNonDefaultBehavior
+ public ConfigurationPropertiesRebinder smartConfigurationPropertiesRebinder(
+ ConfigurationPropertiesBeans beans) {
+ // If using default behavior, not use SmartConfigurationPropertiesRebinder.
+ // Minimize te possibility of making mistakes.
+ return new SmartConfigurationPropertiesRebinder(beans);
+ }
}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/SmartConfigurationPropertiesRebinder.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/SmartConfigurationPropertiesRebinder.java
new file mode 100644
index 000000000..bc275482c
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/SmartConfigurationPropertiesRebinder.java
@@ -0,0 +1,123 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.config.adapter;
+
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import com.tencent.cloud.polaris.config.enums.RefreshBehavior;
+
+import org.springframework.beans.BeansException;
+import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
+import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
+import org.springframework.cloud.context.properties.ConfigurationPropertiesBeans;
+import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.util.ReflectionUtils;
+
+import static com.tencent.cloud.polaris.config.condition.NonDefaultBehaviorCondition.POLARIS_CONFIG_REFRESH_BEHAVIOR;
+import static com.tencent.cloud.polaris.config.enums.RefreshBehavior.ALL_BEANS;
+
+/**
+ * Extend {@link ConfigurationPropertiesRebinder}.
+ *
+ * Spring team doesn't seem to support single {@link ConfigurationPropertiesBean} refresh.
+ *
+ * SmartConfigurationPropertiesRebinder can refresh specific
+ * {@link ConfigurationPropertiesBean} base on the change keys.
+ *
+ * NOTE: We still use Spring's default behavior (full refresh) as default
+ * behavior, This feature can be considered an advanced feature, it may not be as stable
+ * as the default behavior.
+ *
+ * SmartConfigurationPropertiesRebinder
+ *
+ * @author weihubeats 2022-7-10
+ */
+public class SmartConfigurationPropertiesRebinder extends ConfigurationPropertiesRebinder {
+
+ private static final String BEANS = "beans";
+
+ private Map beanMap;
+
+ private ApplicationContext applicationContext;
+
+ private RefreshBehavior refreshBehavior;
+
+ public SmartConfigurationPropertiesRebinder(ConfigurationPropertiesBeans beans) {
+ super(beans);
+ fillBeanMap(beans);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void fillBeanMap(ConfigurationPropertiesBeans beans) {
+ this.beanMap = new HashMap<>();
+ Field field = ReflectionUtils.findField(beans.getClass(), BEANS);
+ if (field != null) {
+ field.setAccessible(true);
+ this.beanMap.putAll((Map) Optional
+ .ofNullable(ReflectionUtils.getField(field, beans))
+ .orElse(Collections.emptyMap()));
+ }
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ super.setApplicationContext(applicationContext);
+ this.applicationContext = applicationContext;
+ this.refreshBehavior = this.applicationContext.getEnvironment().getProperty(
+ POLARIS_CONFIG_REFRESH_BEHAVIOR, RefreshBehavior.class,
+ ALL_BEANS);
+ }
+
+ @Override
+ public void onApplicationEvent(EnvironmentChangeEvent event) {
+ if (this.applicationContext.equals(event.getSource())
+ // Backwards compatible
+ || event.getKeys().equals(event.getSource())) {
+ switch (refreshBehavior) {
+ case SPECIFIC_BEAN:
+ rebindSpecificBean(event);
+ break;
+ default:
+ rebind();
+ break;
+ }
+ }
+ }
+
+ private void rebindSpecificBean(EnvironmentChangeEvent event) {
+ Set refreshedSet = new HashSet<>();
+ beanMap.forEach((name, bean) -> event.getKeys().forEach(changeKey -> {
+ String prefix = AnnotationUtils.getValue(bean.getAnnotation()).toString();
+ // prevent multiple refresh one ConfigurationPropertiesBean.
+ if (changeKey.startsWith(prefix) && refreshedSet.add(name)) {
+ rebind(name);
+ }
+ }));
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/condition/ConditionalOnNonDefaultBehavior.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/condition/ConditionalOnNonDefaultBehavior.java
new file mode 100644
index 000000000..d799ec28b
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/condition/ConditionalOnNonDefaultBehavior.java
@@ -0,0 +1,40 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.config.condition;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.context.annotation.Conditional;
+
+/**
+ * custom annotation.
+ *
+ * @author weihubeats 2022-7-13
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Documented
+@Conditional(NonDefaultBehaviorCondition.class)
+public @interface ConditionalOnNonDefaultBehavior {
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/condition/NonDefaultBehaviorCondition.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/condition/NonDefaultBehaviorCondition.java
new file mode 100644
index 000000000..98b14318e
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/condition/NonDefaultBehaviorCondition.java
@@ -0,0 +1,57 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+package com.tencent.cloud.polaris.config.condition;
+
+import com.tencent.cloud.polaris.config.enums.RefreshBehavior;
+
+import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
+import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * Extend SpringBootCondition.
+ *
+ * @author weihubeats 2022-7-13
+ */
+public class NonDefaultBehaviorCondition extends SpringBootCondition {
+
+ /**
+ * refresh behavior config.
+ */
+ public static final String POLARIS_CONFIG_REFRESH_BEHAVIOR = "spring.cloud.polaris.config.refresh-behavior";
+
+ /**
+ * refresh behavior config default value.
+ */
+ private static final RefreshBehavior DEFAULT_REFRESH_BEHAVIOR = RefreshBehavior.ALL_BEANS;
+
+ @Override
+ public ConditionOutcome getMatchOutcome(ConditionContext context,
+ AnnotatedTypeMetadata metadata) {
+ RefreshBehavior behavior = context.getEnvironment().getProperty(
+ POLARIS_CONFIG_REFRESH_BEHAVIOR, RefreshBehavior.class,
+ DEFAULT_REFRESH_BEHAVIOR);
+ if (DEFAULT_REFRESH_BEHAVIOR == behavior) {
+ return ConditionOutcome.noMatch("no matched");
+ }
+ return ConditionOutcome.match("matched");
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/RefreshBehavior.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/RefreshBehavior.java
new file mode 100644
index 000000000..12abd79cb
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/RefreshBehavior.java
@@ -0,0 +1,40 @@
+/*
+ * Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
+ *
+ * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
+ *
+ * Licensed under the BSD 3-Clause License (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ *
+ */
+
+
+package com.tencent.cloud.polaris.config.enums;
+
+import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
+
+/**
+ * Refresh behavior.
+ *
+ * @author weihubeats 2022-7-13
+ */
+public enum RefreshBehavior {
+
+ /**
+ * Refresh all {@link ConfigurationPropertiesBean}s.
+ */
+ ALL_BEANS,
+ /**
+ * Refresh specific {@link ConfigurationPropertiesBean} base on change key.
+ */
+ SPECIFIC_BEAN,
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 9954a62ce..3de4948d4 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -41,6 +41,12 @@
"defaultValue": "true",
"description": "Whether to connect to a remote server, suitable for local development mode.",
"sourceType": "com.tencent.cloud.polaris.config.config.PolarisConfigProperties"
+ },
+ {
+ "name": "spring.cloud.polaris.config.refresh-behavior",
+ "type": "com.tencent.cloud.polaris.config.enums.RefreshBehavior",
+ "defaultValue": "all_beans",
+ "description": "ConfigurationPropertiesBean refresh behavior."
}
]
}