configFileGroups) {
String namespace = polarisContextProperties.getNamespace();
@@ -125,12 +191,10 @@ public class PolarisConfigFileLocator implements PropertySourceLocator {
// unknown extension is resolved as properties file
if (ConfigFileFormat.isPropertyFile(fileName)
|| ConfigFileFormat.isUnknownFile(fileName)) {
- configKVFile = configFileService.getConfigPropertiesFile(namespace, group,
- fileName);
+ configKVFile = configFileService.getConfigPropertiesFile(namespace, group, fileName);
}
else if (ConfigFileFormat.isYamlFile(fileName)) {
- configKVFile = configFileService.getConfigYamlFile(namespace, group,
- fileName);
+ configKVFile = configFileService.getConfigYamlFile(namespace, group, fileName);
}
else {
LOGGER.warn(
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/annotation/PolarisConfigAnnotationProcessor.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/annotation/PolarisConfigAnnotationProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..349799f6957fe49ce6d7f4087d622679102797e4
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/annotation/PolarisConfigAnnotationProcessor.java
@@ -0,0 +1,105 @@
+/*
+ * 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.annotation;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.tencent.cloud.polaris.config.listener.ConfigChangeEvent;
+import com.tencent.cloud.polaris.config.listener.ConfigChangeListener;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.core.Ordered;
+import org.springframework.core.PriorityOrdered;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.lang.NonNull;
+import org.springframework.util.ReflectionUtils;
+
+import static com.tencent.cloud.polaris.config.listener.PolarisConfigListenerContext.addChangeListener;
+
+/**
+ * {@link PolarisConfigAnnotationProcessor} implementation for spring .
+ * Refer to the Apollo project implementation:
+ *
+ * ApolloAnnotationProcessor
+ * @author Palmer Xu 2022-06-07
+ */
+public class PolarisConfigAnnotationProcessor implements BeanPostProcessor, PriorityOrdered {
+
+ @Override
+ public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName)
+ throws BeansException {
+ Class> clazz = bean.getClass();
+ for (Method method : findAllMethod(clazz)) {
+ this.processPolarisConfigChangeListener(bean, method);
+ }
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public int getOrder() {
+ return Ordered.LOWEST_PRECEDENCE;
+ }
+
+ private List findAllMethod(Class> clazz) {
+ final List res = new LinkedList<>();
+ ReflectionUtils.doWithMethods(clazz, res::add);
+ return res;
+ }
+
+ private void processPolarisConfigChangeListener(final Object bean, final Method method) {
+ PolarisConfigKVFileChangeListener annotation = AnnotationUtils
+ .findAnnotation(method, PolarisConfigKVFileChangeListener.class);
+ if (annotation == null) {
+ return;
+ }
+ Class>[] parameterTypes = method.getParameterTypes();
+ Preconditions.checkArgument(parameterTypes.length == 1,
+ "Invalid number of parameters: %s for method: %s, should be 1", parameterTypes.length,
+ method);
+ Preconditions.checkArgument(ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0]),
+ "Invalid parameter type: %s for method: %s, should be ConfigChangeEvent", parameterTypes[0],
+ method);
+
+ ReflectionUtils.makeAccessible(method);
+ String[] annotatedInterestedKeys = annotation.interestedKeys();
+ String[] annotatedInterestedKeyPrefixes = annotation.interestedKeyPrefixes();
+
+ ConfigChangeListener configChangeListener = changeEvent -> ReflectionUtils.invokeMethod(method, bean, changeEvent);
+
+ Set interestedKeys =
+ annotatedInterestedKeys.length > 0 ? Sets.newHashSet(annotatedInterestedKeys) : null;
+ Set interestedKeyPrefixes =
+ annotatedInterestedKeyPrefixes.length > 0 ? Sets.newHashSet(annotatedInterestedKeyPrefixes)
+ : null;
+
+ addChangeListener(configChangeListener, interestedKeys, interestedKeyPrefixes);
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/annotation/PolarisConfigKVFileChangeListener.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/annotation/PolarisConfigKVFileChangeListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..142b41bed28dde1d3d68753f2f6c01b447228a05
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/annotation/PolarisConfigKVFileChangeListener.java
@@ -0,0 +1,58 @@
+/*
+ * 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.annotation;
+
+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;
+
+/**
+ * Configuring the change listener annotation.
+ * Refer to the Apollo project implementation:
+ *
+ * ApolloAnnotationProcessor
+ * @author Palmer Xu 2022-05-31
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Documented
+public @interface PolarisConfigKVFileChangeListener {
+
+ /**
+ * The keys interested in the listener, will only be notified if any of the interested keys is changed.
+ *
+ * If neither of {@code interestedKeys} and {@code interestedKeyPrefixes} is specified then the {@code listener} will be notified when any key is changed.
+ * @return interested keys in the listener
+ */
+ String[] interestedKeys() default {};
+
+ /**
+ * The key prefixes that the listener is interested in, will be notified if and only if the changed keys start with anyone of the prefixes.
+ * The prefixes will simply be used to determine whether the {@code listener} should be notified or not using {@code changedKey.startsWith(prefix)}.
+ * e.g. "spring." means that {@code listener} is interested in keys that starts with "spring.", such as "spring.banner", "spring.jpa", etc.
+ * and "application" means that {@code listener} is interested in keys that starts with "application", such as "applicationName", "application.port", etc.
+ *
+ * If neither of {@code interestedKeys} and {@code interestedKeyPrefixes} is specified then the {@code listener} will be notified when whatever key is changed.
+ * @return interested key-prefixed in the listener
+ */
+ String[] interestedKeyPrefixes() default {};
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/config/PolarisConfigProperties.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/config/PolarisConfigProperties.java
index 6ddc49f5fcd49622ad21d4facc2cf47c82a5e0bf..a2c9032fe4ccbfb9be31f6559dbfe40fbe2059d7 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/config/PolarisConfigProperties.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/config/PolarisConfigProperties.java
@@ -39,6 +39,11 @@ public class PolarisConfigProperties {
*/
private String address;
+ /**
+ * Polaris config grpc port.
+ */
+ private int port = 8093;
+
/**
* Whether to automatically update to the spring context when the configuration file.
* is updated
@@ -66,6 +71,14 @@ public class PolarisConfigProperties {
this.address = address;
}
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
public boolean isAutoRefresh() {
return autoRefresh;
}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb9e94f5b3052a0d6fd2e35e5d74bd632bbc2854
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpoint.java
@@ -0,0 +1,58 @@
+/*
+ * 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.endpoint;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.tencent.cloud.polaris.config.adapter.PolarisPropertySource;
+import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
+import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
+
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+
+/**
+ * Endpoint of polaris config.
+ *
+ * @author shuiqingliu
+ **/
+@Endpoint(id = "polaris-config")
+public class PolarisConfigEndpoint {
+
+ private final PolarisConfigProperties polarisConfigProperties;
+ private final PolarisPropertySourceManager polarisPropertySourceManager;
+
+ public PolarisConfigEndpoint(PolarisConfigProperties polarisConfigProperties, PolarisPropertySourceManager polarisPropertySourceManager) {
+ this.polarisConfigProperties = polarisConfigProperties;
+ this.polarisPropertySourceManager = polarisPropertySourceManager;
+ }
+
+ @ReadOperation
+ public Map polarisConfig() {
+ Map configInfo = new HashMap<>();
+ configInfo.put("PolarisConfigProperties", polarisConfigProperties);
+
+ List propertySourceList = polarisPropertySourceManager.getAllPropertySources();
+ configInfo.put("PolarisPropertySource", propertySourceList);
+
+ return configInfo;
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb26462ee44d4bdd250f5392df130522fa66f4b7
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/endpoint/PolarisConfigEndpointAutoConfiguration.java
@@ -0,0 +1,49 @@
+/*
+ * 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.endpoint;
+
+import com.tencent.cloud.polaris.config.adapter.PolarisPropertySourceManager;
+import com.tencent.cloud.polaris.config.config.PolarisConfigProperties;
+
+import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * The AutoConfiguration for Polaris Config's endpoint.
+ *
+ * @author shuiqingliu
+ **/
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnClass(Endpoint.class)
+@ConditionalOnProperty(value = "spring.cloud.polaris.config.enabled",
+ matchIfMissing = true)
+public class PolarisConfigEndpointAutoConfiguration {
+
+ @Bean
+ @ConditionalOnAvailableEndpoint
+ @ConditionalOnMissingBean
+ public PolarisConfigEndpoint polarisConfigEndpoint(PolarisConfigProperties polarisConfigProperties, PolarisPropertySourceManager polarisPropertySourceManager) {
+ return new PolarisConfigEndpoint(polarisConfigProperties, polarisPropertySourceManager);
+ }
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/ConfigFileFormat.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/ConfigFileFormat.java
index 2b7be5774ef147d9a10d46485e65e33f79211fcc..024ad67d0dba1a763e2c88932e044251b8cbd486 100644
--- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/ConfigFileFormat.java
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/enums/ConfigFileFormat.java
@@ -28,7 +28,7 @@ public enum ConfigFileFormat {
/**
* property format.
*/
- PROPERTY(".property"),
+ PROPERTY(".properties"),
/**
* yaml format.
*/
@@ -48,7 +48,7 @@ public enum ConfigFileFormat {
/**
* text format.
*/
- TEXT(".text"),
+ TEXT(".txt"),
/**
* html format.
*/
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/ConfigChangeEvent.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/ConfigChangeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..119a5ce4c8fcebc6cab0b29a2e75afbc2799b1d4
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/ConfigChangeEvent.java
@@ -0,0 +1,88 @@
+/*
+ * 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.listener;
+
+import java.util.Map;
+import java.util.Set;
+
+import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
+
+/**
+ * A change event when config is changed .
+ *
+ * @author Palmer Xu 2022-06-07
+ */
+public final class ConfigChangeEvent {
+
+ /**
+ * all changes keys map.
+ */
+ private final Map changes;
+
+ /**
+ * all interested changed keys.
+ */
+ private final Set interestedChangedKeys;
+
+ /**
+ * Config Change Event Constructor.
+ * @param changes all changes keys map
+ * @param interestedChangedKeys all interested changed keys
+ */
+ public ConfigChangeEvent(Map changes, Set interestedChangedKeys) {
+ this.changes = changes;
+ this.interestedChangedKeys = interestedChangedKeys;
+ }
+
+ /**
+ * Get the keys changed.
+ * @return the list of the keys
+ */
+ public Set changedKeys() {
+ return changes.keySet();
+ }
+
+ /**
+ * Get a specific change instance for the key specified.
+ * @param key the changed key
+ * @return the change instance
+ */
+ public ConfigPropertyChangeInfo getChange(String key) {
+ return changes.get(key);
+ }
+
+ /**
+ * Check whether the specified key is changed .
+ * @param key the key
+ * @return true if the key is changed, false otherwise.
+ */
+ public boolean isChanged(String key) {
+ return changes.containsKey(key);
+ }
+
+ /**
+ * Maybe subclass override this method.
+ *
+ * @return interested and changed keys
+ */
+ public Set interestedChangedKeys() {
+ return interestedChangedKeys;
+ }
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListener.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..14ab64a321132eb08ac7be2062e5658a9d35680e
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/ConfigChangeListener.java
@@ -0,0 +1,35 @@
+/*
+ * 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.listener;
+
+/**
+ * Configuring the change listener interface.
+ *
+ * @author Palmer Xu 2022-05-31
+ */
+public interface ConfigChangeListener {
+
+ /**
+ * Invoked when there is any config change for the namespace.
+ *
+ * @param changeEvent the event for this change
+ */
+ void onChange(ConfigChangeEvent changeEvent);
+
+}
diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/PolarisConfigChangeEventListener.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/PolarisConfigChangeEventListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a55255d533bf34adf78223a93806b34cf4cd5fa
--- /dev/null
+++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/listener/PolarisConfigChangeEventListener.java
@@ -0,0 +1,111 @@
+/*
+ * 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.listener;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.google.common.collect.Maps;
+import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo;
+
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.lang.NonNull;
+
+import static com.tencent.cloud.polaris.config.listener.PolarisConfigListenerContext.fireConfigChange;
+import static com.tencent.cloud.polaris.config.listener.PolarisConfigListenerContext.initialize;
+import static com.tencent.cloud.polaris.config.listener.PolarisConfigListenerContext.merge;
+
+/**
+ * Polaris Config Change Event Listener .
+ *
+ * @author Elve.Xu 2022-06-08
+ */
+public final class PolarisConfigChangeEventListener implements ApplicationListener {
+
+ private static final AtomicBoolean started = new AtomicBoolean();
+
+ /**
+ * Handle an application event.
+ *
+ * @param event the event to respond to
+ */
+ @Override
+ public void onApplicationEvent(@NonNull ApplicationEvent event) {
+
+ // Initialize application all environment properties .
+ if (event instanceof ApplicationStartedEvent && started.compareAndSet(false, true)) {
+ ApplicationStartedEvent applicationStartedEvent = (ApplicationStartedEvent) event;
+ ConfigurableEnvironment environment = applicationStartedEvent.getApplicationContext().getEnvironment();
+ Map ret = loadEnvironmentProperties(environment);
+ if (!ret.isEmpty()) {
+ initialize(ret);
+ }
+ }
+
+ // Process Environment Change Event .
+ if (event instanceof EnvironmentChangeEvent) {
+ EnvironmentChangeEvent environmentChangeEvent = (EnvironmentChangeEvent) event;
+ ConfigurableApplicationContext context = (ConfigurableApplicationContext) environmentChangeEvent.getSource();
+ ConfigurableEnvironment environment = context.getEnvironment();
+ Map ret = loadEnvironmentProperties(environment);
+ Map changes = merge(ret);
+ fireConfigChange(changes.keySet(), Maps.newHashMap(changes));
+ changes.clear();
+ }
+ }
+
+ /**
+ * Try load all application environment config properties .
+ * @param environment application environment instance of {@link Environment}
+ * @return properties
+ */
+ @SuppressWarnings("unchecked")
+ private Map loadEnvironmentProperties(ConfigurableEnvironment environment) {
+ Map ret = Maps.newHashMap();
+ MutablePropertySources sources = environment.getPropertySources();
+ sources.iterator().forEachRemaining(propertySource -> {
+ Object o = propertySource.getSource();
+ if (o instanceof Map) {
+ for (Map.Entry entry : ((Map) o).entrySet()) {
+ String key = entry.getKey();
+ String value = environment.getProperty(key);
+ ret.put(key, value);
+ }
+ }
+ else if (o instanceof Collection) {
+ int count = 0;
+ Collection