From 15d3b880371de5ec61e41f049825f64b9f62c095 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 7 Dec 2014 16:30:31 +0100 Subject: [PATCH] DefaultSingletonBeanRegistry's isDependent defensively checks for circular recursion Issue: SPR-10787 --- .../support/DefaultSingletonBeanRegistry.java | 15 ++++++++++++- .../DefaultSingletonBeanRegistryTests.java | 22 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) rename spring-beans/src/test/java/org/springframework/beans/factory/{ => support}/DefaultSingletonBeanRegistryTests.java (76%) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java index 73441b9f33f..e1790d5bf5d 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java @@ -18,6 +18,7 @@ package org.springframework.beans.factory.support; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -441,9 +442,17 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements * dependent on the given bean or on any of its transitive dependencies. * @param beanName the name of the bean to check * @param dependentBeanName the name of the dependent bean + * @since 4.0 */ protected boolean isDependent(String beanName, String dependentBeanName) { + return isDependent(beanName, dependentBeanName, null); + } + + private boolean isDependent(String beanName, String dependentBeanName, Set alreadySeen) { String canonicalName = canonicalName(beanName); + if (alreadySeen != null && alreadySeen.contains(beanName)) { + return false; + } Set dependentBeans = this.dependentBeanMap.get(canonicalName); if (dependentBeans == null) { return false; @@ -452,7 +461,11 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements return true; } for (String transitiveDependency : dependentBeans) { - if (isDependent(transitiveDependency, dependentBeanName)) { + if (alreadySeen == null) { + alreadySeen = new HashSet(); + } + alreadySeen.add(beanName); + if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) { return true; } } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultSingletonBeanRegistryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistryTests.java similarity index 76% rename from spring-beans/src/test/java/org/springframework/beans/factory/DefaultSingletonBeanRegistryTests.java rename to spring-beans/src/test/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistryTests.java index 037afde7558..1b49c287abc 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultSingletonBeanRegistryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistryTests.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.springframework.beans.factory; +package org.springframework.beans.factory.support; import org.junit.Test; import org.springframework.beans.BeansException; -import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry; +import org.springframework.beans.factory.ObjectFactory; import org.springframework.tests.sample.beans.DerivedTestBean; import org.springframework.tests.sample.beans.TestBean; @@ -83,4 +83,22 @@ public class DefaultSingletonBeanRegistryTests { assertTrue(tb.wasDestroyed()); } + @Test + public void testDependentRegistration() { + DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry(); + + beanRegistry.registerDependentBean("a", "b"); + beanRegistry.registerDependentBean("b", "c"); + beanRegistry.registerDependentBean("c", "b"); + assertTrue(beanRegistry.isDependent("a", "b")); + assertTrue(beanRegistry.isDependent("b", "c")); + assertTrue(beanRegistry.isDependent("c", "b")); + assertTrue(beanRegistry.isDependent("a", "c")); + assertFalse(beanRegistry.isDependent("c", "a")); + assertFalse(beanRegistry.isDependent("b", "a")); + assertFalse(beanRegistry.isDependent("a", "a")); + assertTrue(beanRegistry.isDependent("b", "b")); + assertTrue(beanRegistry.isDependent("c", "c")); + } + }