From 4f3ed9321c592cb08dfaf5b7621326585adf9381 Mon Sep 17 00:00:00 2001 From: DerekYRC <44155264+DerekYRC@users.noreply.github.com> Date: Fri, 19 Aug 2022 10:04:47 +0800 Subject: [PATCH] BeanFactoryUtils returns all beans including beans defined in ancestor bean factories (#515) --- CHANGELOG.md | 1 + ...cerCompositeRuleBeanPostProcessorTest.java | 26 +++++++++++++- .../cloud/common/util/BeanFactoryUtils.java | 22 +++++------- .../common/util/BeanFactoryUtilsTest.java | 36 +++++++++++++++++++ 4 files changed, 70 insertions(+), 15 deletions(-) create mode 100644 spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/BeanFactoryUtilsTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index b4c0cdcc..faa440af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,3 +10,4 @@ - [Feature: zuul supports polaris router](https://github.com/Tencent/spring-cloud-tencent/pull/502) - [Refactor : optimize project and code](https://github.com/Tencent/spring-cloud-tencent/pull/506) - [Fix typo & Code optimization](https://github.com/Tencent/spring-cloud-tencent/pull/507) +- [Bugfix:BeanFactoryUtils returns all beans including beans defined in ancestor bean factories](https://github.com/Tencent/spring-cloud-tencent/pull/515) diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/PolarisLoadBalancerCompositeRuleBeanPostProcessorTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/PolarisLoadBalancerCompositeRuleBeanPostProcessorTest.java index 009d6a77..94274465 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/PolarisLoadBalancerCompositeRuleBeanPostProcessorTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/beanprocessor/PolarisLoadBalancerCompositeRuleBeanPostProcessorTest.java @@ -18,15 +18,21 @@ package com.tencent.cloud.polaris.router.beanprocessor; +import java.util.List; + import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.BestAvailableRule; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; import com.netflix.loadbalancer.RoundRobinRule; import com.netflix.loadbalancer.ZoneAvoidanceRule; +import com.tencent.cloud.common.util.ReflectionUtils; import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties; import com.tencent.cloud.polaris.router.PolarisLoadBalancerCompositeRule; import com.tencent.cloud.polaris.router.config.RibbonConfiguration; +import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterProperties; +import com.tencent.cloud.polaris.router.interceptor.NearbyRouterRequestInterceptor; +import com.tencent.cloud.polaris.router.spi.RouterRequestInterceptor; import com.tencent.polaris.client.api.SDKContext; import com.tencent.polaris.router.api.core.RouterAPI; import com.tencent.polaris.router.client.api.DefaultRouterAPI; @@ -34,6 +40,7 @@ import org.junit.Assert; import org.junit.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; @@ -42,6 +49,7 @@ import org.springframework.cloud.netflix.ribbon.RibbonClients; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.CollectionUtils; /** * Test for {@link PolarisLoadBalancerCompositeRuleBeanPostProcessor}. @@ -57,12 +65,18 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessorTest { @Test public void test1() { ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(RibbonDefaultConfig.class, PolarisRibbonTest.class, RibbonAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of( + RibbonDefaultConfig.class, + PolarisRibbonTest.class, + RibbonAutoConfiguration.class, + RouterConfiguration.class)); contextRunner.run(context -> { SpringClientFactory springClientFactory = context.getBean(SpringClientFactory.class); IRule rule = springClientFactory.getInstance(SERVICE_1, IRule.class); Assert.assertTrue(rule instanceof PolarisLoadBalancerCompositeRule); + List requestInterceptors = (List) ReflectionUtils.getFieldValue(rule, "requestInterceptors"); + Assert.assertFalse(CollectionUtils.isEmpty(requestInterceptors)); AbstractLoadBalancerRule delegateRule = ((PolarisLoadBalancerCompositeRule) rule).getDelegateRule(); //ZoneAvoidanceRule default Assert.assertTrue(delegateRule instanceof ZoneAvoidanceRule); @@ -162,4 +176,14 @@ public class PolarisLoadBalancerCompositeRuleBeanPostProcessorTest { return new DefaultRouterAPI(sdkContext); } } + + @Configuration + @EnableConfigurationProperties(PolarisNearByRouterProperties.class) + static class RouterConfiguration { + @Bean + @ConditionalOnProperty(value = "spring.cloud.polaris.router.nearby-router.enabled", matchIfMissing = true) + public NearbyRouterRequestInterceptor nearbyRouterRequestInterceptor(PolarisNearByRouterProperties polarisNearByRouterProperties) { + return new NearbyRouterRequestInterceptor(polarisNearByRouterProperties); + } + } } diff --git a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.java b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.java index bddde813..e7729cf1 100644 --- a/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.java +++ b/spring-cloud-tencent-commons/src/main/java/com/tencent/cloud/common/util/BeanFactoryUtils.java @@ -18,13 +18,14 @@ package com.tencent.cloud.common.util; -import java.util.Arrays; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; +import java.util.Map; import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.ListableBeanFactory; + +import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; /** * the utils for bean factory. @@ -36,19 +37,12 @@ public final class BeanFactoryUtils { } public static List getBeans(BeanFactory beanFactory, Class requiredType) { - if (!(beanFactory instanceof DefaultListableBeanFactory)) { + if (!(beanFactory instanceof ListableBeanFactory)) { throw new RuntimeException("bean factory not support get list bean. factory type = " + beanFactory.getClass() .getName()); } - String[] beanNames = ((DefaultListableBeanFactory) beanFactory).getBeanNamesForType(requiredType); - - if (beanNames.length == 0) { - return Collections.emptyList(); - } - - return Arrays.stream(beanNames).map( - beanName -> beanFactory.getBean(beanName, requiredType) - ).collect(Collectors.toList()); + Map beanMap = beansOfTypeIncludingAncestors((ListableBeanFactory) beanFactory, requiredType); + return new ArrayList<>(beanMap.values()); } } diff --git a/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/BeanFactoryUtilsTest.java b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/BeanFactoryUtilsTest.java new file mode 100644 index 00000000..aa1b4b49 --- /dev/null +++ b/spring-cloud-tencent-commons/src/test/java/com/tencent/cloud/common/util/BeanFactoryUtilsTest.java @@ -0,0 +1,36 @@ +package com.tencent.cloud.common.util; + +import org.junit.Assert; +import org.junit.Test; + +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; + +/** + * Test for {@link BeanFactoryUtils}. + * + * @author Derek Yi 2022-08-18 + */ +public class BeanFactoryUtilsTest { + + @Test + public void testGetBeansIncludingAncestors() { + DefaultListableBeanFactory parentBeanFactory = new DefaultListableBeanFactory(); + parentBeanFactory.registerBeanDefinition("foo", new RootBeanDefinition(Foo.class)); + + DefaultListableBeanFactory childBeanFactory = new DefaultListableBeanFactory(parentBeanFactory); + + Assert.assertTrue(childBeanFactory.getBeansOfType(Foo.class).isEmpty()); + Assert.assertTrue(BeanFactoryUtils.getBeans(childBeanFactory, Foo.class).size() == 1); + + Assert.assertTrue(BeanFactoryUtils.getBeans(childBeanFactory, Bar.class).isEmpty()); + } + + static class Foo { + + } + + static class Bar { + + } +}