diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cdd84ad..fa589fc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,3 +21,4 @@ - [Feature: support read config file from local file system](https://github.com/Tencent/spring-cloud-tencent/pull/640) - [fix:optimize expression parser V1.](https://github.com/Tencent/spring-cloud-tencent/pull/642) - [Optimize: add transfer metadata unit test.](https://github.com/Tencent/spring-cloud-tencent/pull/646) +- [feat: publish spring event named ConfigChangeSpringEvent when the configuration is changed](https://github.com/Tencent/spring-cloud-tencent/pull/647) 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 index 90189899..087f9f6e 100644 --- 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 @@ -23,11 +23,14 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import com.google.common.collect.Maps; +import com.tencent.cloud.polaris.config.spring.event.ConfigChangeSpringEvent; 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.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationListener; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; @@ -44,10 +47,12 @@ import static com.tencent.cloud.polaris.config.listener.PolarisConfigListenerCon * * @author Elve.Xu 2022-06-08 */ -public final class PolarisConfigChangeEventListener implements ApplicationListener { +public final class PolarisConfigChangeEventListener implements ApplicationListener, ApplicationEventPublisherAware { private static final AtomicBoolean started = new AtomicBoolean(); + private ApplicationEventPublisher eventPublisher; + /** * Handle an application event. * @@ -72,6 +77,8 @@ public final class PolarisConfigChangeEventListener implements ApplicationListen ConfigurableEnvironment environment = context.getEnvironment(); Map ret = loadEnvironmentProperties(environment); Map changes = merge(ret); + ConfigChangeSpringEvent configChangeSpringEvent = new ConfigChangeSpringEvent(Maps.newHashMap(changes)); + eventPublisher.publishEvent(configChangeSpringEvent); fireConfigChange(changes.keySet(), Maps.newHashMap(changes)); changes.clear(); } @@ -106,4 +113,9 @@ public final class PolarisConfigChangeEventListener implements ApplicationListen }); return ret; } + + @Override + public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) { + this.eventPublisher = eventPublisher; + } } diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/spring/event/ConfigChangeSpringEvent.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/spring/event/ConfigChangeSpringEvent.java new file mode 100644 index 00000000..cd5eca7e --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/spring/event/ConfigChangeSpringEvent.java @@ -0,0 +1,70 @@ +/* + * 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.spring.event; + +import java.util.Map; +import java.util.Set; + +import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo; + +import org.springframework.context.ApplicationEvent; + +/** + * A spring change event when config is changed. + * + * @author Derek Yi 2022-10-16 + */ +public class ConfigChangeSpringEvent extends ApplicationEvent { + /** + * @param source all changed keys map. + */ + public ConfigChangeSpringEvent(Map source) { + super(source); + } + + /** + * Get the changed keys. + * @return the list of the keys + */ + public Set changedKeys() { + return changeMap().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 changeMap().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 changeMap().containsKey(key); + } + + private Map changeMap() { + return (Map) getSource(); + } +} diff --git a/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/spring/event/ConfigChangeSpringEventTest.java b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/spring/event/ConfigChangeSpringEventTest.java new file mode 100644 index 00000000..2e44c476 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-config/src/test/java/com/tencent/cloud/polaris/config/spring/event/ConfigChangeSpringEventTest.java @@ -0,0 +1,80 @@ +/* + * 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.spring.event; + +import java.util.HashMap; +import java.util.Set; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import com.tencent.polaris.configuration.api.core.ChangeType; +import com.tencent.polaris.configuration.api.core.ConfigPropertyChangeInfo; +import org.junit.Assert; +import org.junit.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Configuration; + + +/** + * Test for {@link ConfigChangeSpringEvent}. + * + * @author derek.yi 2022-10-16 + */ +public class ConfigChangeSpringEventTest { + + private static CountDownLatch countDownLatch = new CountDownLatch(1); + + private static AtomicInteger receiveEventTimes = new AtomicInteger(); + + @Test + public void testPublishConfigChangeSpringEvent() { + ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(ConfigChangeSpringEventListener.class)); + contextRunner.run(context -> { + HashMap changeMap = new HashMap<>(); + changeMap.put("key", new ConfigPropertyChangeInfo("key", null, "value", ChangeType.ADDED)); + context.publishEvent(new ConfigChangeSpringEvent(changeMap)); + countDownLatch.await(5, TimeUnit.SECONDS); + Assert.assertEquals(1, receiveEventTimes.get()); + }); + } + + @Configuration + static class ConfigChangeSpringEventListener implements ApplicationListener { + + @Override + public void onApplicationEvent(ConfigChangeSpringEvent event) { + Set changedKeys = event.changedKeys(); + Assert.assertEquals(1, changedKeys.size()); + Assert.assertTrue(event.isChanged("key")); + ConfigPropertyChangeInfo changeInfo = event.getChange("key"); + Assert.assertNotNull(changeInfo); + Assert.assertEquals("key", changeInfo.getPropertyName()); + Assert.assertEquals("value", changeInfo.getNewValue()); + Assert.assertEquals(ChangeType.ADDED, changeInfo.getChangeType()); + + receiveEventTimes.incrementAndGet(); + countDownLatch.countDown(); + } + } +}