diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java index f68d91048..81efe6252 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/PolarisRefreshConfiguration.java @@ -23,6 +23,7 @@ import com.tencent.cloud.polaris.discovery.ConditionalOnPolarisDiscoveryEnabled; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; /** * Configuration for listening the change of service status. @@ -41,8 +42,8 @@ public class PolarisRefreshConfiguration { @Bean @ConditionalOnMissingBean - public ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager() { - return new ServiceInstanceChangeCallbackManager(); + public ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager(Environment environment) { + return new ServiceInstanceChangeCallbackManager(environment); } @Bean diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java index 7a12db4b0..a0eb0e1cb 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/main/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackManager.java @@ -35,6 +35,7 @@ import reactor.util.annotation.NonNull; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; +import org.springframework.core.env.Environment; import org.springframework.util.CollectionUtils; /** @@ -50,7 +51,10 @@ public class ServiceInstanceChangeCallbackManager implements ApplicationListener private final ScheduledThreadPoolExecutor serviceChangeListenerExecutor; - public ServiceInstanceChangeCallbackManager() { + private final Environment environment; + + public ServiceInstanceChangeCallbackManager(Environment environment) { + this.environment = environment; this.serviceChangeListenerExecutor = new ScheduledThreadPoolExecutor(4, new NamedThreadFactory("service-change-listener")); } @@ -101,7 +105,7 @@ public class ServiceInstanceChangeCallbackManager implements ApplicationListener if (clz.isAnnotationPresent(ServiceInstanceChangeListener.class)) { ServiceInstanceChangeListener serviceInstanceChangeListener = clz.getAnnotation(ServiceInstanceChangeListener.class); serviceName = serviceInstanceChangeListener.serviceName(); - serviceName = ApplicationContextAwareUtils.getApplicationContext().getEnvironment().resolvePlaceholders(serviceName); + serviceName = environment.resolvePlaceholders(serviceName); } if (StringUtils.isBlank(serviceName)) { diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackTest.java new file mode 100644 index 000000000..c8cf0c182 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/polaris/discovery/refresh/ServiceInstanceChangeCallbackTest.java @@ -0,0 +1,120 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 Tencent. 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.discovery.refresh; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import com.tencent.cloud.polaris.registry.PolarisAutoServiceRegistration; +import com.tencent.polaris.api.pojo.Instance; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +/** + * Test for {@link ServiceInstanceChangeCallback}. + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = RANDOM_PORT, + classes = ServiceInstanceChangeCallbackTest.TestApplication.class, + properties = {"spring.config.location = classpath:application-test.yml", + "spring.main.web-application-type = servlet", + "spring.cloud.gateway.enabled = false"}) +public class ServiceInstanceChangeCallbackTest { + + @Autowired + ServiceInstanceChangeCallbackManager serviceInstanceChangeCallbackManager; + + @Test + public void test1() { + // Get callbackMap from serviceInstanceChangeCallbackManager via reflection + try { + Field callbackMapField = ServiceInstanceChangeCallbackManager.class.getDeclaredField("callbackMap"); + callbackMapField.setAccessible(true); + ConcurrentHashMap> callbackMap = + (ConcurrentHashMap>) callbackMapField.get(serviceInstanceChangeCallbackManager); + + // Verify + assertThat(callbackMap.containsKey("java_provider_test")).isTrue(); + assertThat(callbackMap.containsKey("QuickstartCalleeService")).isTrue(); + + } + catch (Exception e) { + throw new RuntimeException("Failed to get callbackMap via reflection", e); + } + } + + @SpringBootApplication + protected static class TestApplication { + + @Bean + public SelfServiceChangeCallback selfServiceChangeCallback() { + return new SelfServiceChangeCallback(); + } + + @Bean + public CalleeServiceChangeCallback calleeServiceChangeCallback() { + return new CalleeServiceChangeCallback(); + } + + @Bean + public TestBeanPostProcessor testBeanPostProcessor() { + return new TestBeanPostProcessor(); + } + + } + + @ServiceInstanceChangeListener(serviceName = "${spring.application.name}") + static class SelfServiceChangeCallback implements ServiceInstanceChangeCallback { + + @Override + public void callback(List currentServiceInstances, List addServiceInstances, List deleteServiceInstances) { + + } + } + + @ServiceInstanceChangeListener(serviceName = "QuickstartCalleeService") + static class CalleeServiceChangeCallback implements ServiceInstanceChangeCallback { + + @Override + public void callback(List currentServiceInstances, List addServiceInstances, List deleteServiceInstances) { + + } + } + + static class TestBeanPostProcessor implements BeanPostProcessor { + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + if (bean instanceof PolarisAutoServiceRegistration) { + return org.mockito.Mockito.mock(PolarisAutoServiceRegistration.class); + } + return bean; + } + } +}