Skip to content

Commit 15d3b88

Browse files
committed
DefaultSingletonBeanRegistry's isDependent defensively checks for circular recursion
Issue: SPR-10787
1 parent 1daa5eb commit 15d3b88

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Collections;
2020
import java.util.HashMap;
21+
import java.util.HashSet;
2122
import java.util.Iterator;
2223
import java.util.LinkedHashMap;
2324
import java.util.LinkedHashSet;
@@ -441,9 +442,17 @@ public void registerDependentBean(String beanName, String dependentBeanName) {
441442
* dependent on the given bean or on any of its transitive dependencies.
442443
* @param beanName the name of the bean to check
443444
* @param dependentBeanName the name of the dependent bean
445+
* @since 4.0
444446
*/
445447
protected boolean isDependent(String beanName, String dependentBeanName) {
448+
return isDependent(beanName, dependentBeanName, null);
449+
}
450+
451+
private boolean isDependent(String beanName, String dependentBeanName, Set<String> alreadySeen) {
446452
String canonicalName = canonicalName(beanName);
453+
if (alreadySeen != null && alreadySeen.contains(beanName)) {
454+
return false;
455+
}
447456
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
448457
if (dependentBeans == null) {
449458
return false;
@@ -452,7 +461,11 @@ protected boolean isDependent(String beanName, String dependentBeanName) {
452461
return true;
453462
}
454463
for (String transitiveDependency : dependentBeans) {
455-
if (isDependent(transitiveDependency, dependentBeanName)) {
464+
if (alreadySeen == null) {
465+
alreadySeen = new HashSet<String>();
466+
}
467+
alreadySeen.add(beanName);
468+
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
456469
return true;
457470
}
458471
}

spring-beans/src/test/java/org/springframework/beans/factory/DefaultSingletonBeanRegistryTests.java renamed to spring-beans/src/test/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistryTests.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.beans.factory;
17+
package org.springframework.beans.factory.support;
1818

1919
import org.junit.Test;
2020

2121
import org.springframework.beans.BeansException;
22-
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
22+
import org.springframework.beans.factory.ObjectFactory;
2323
import org.springframework.tests.sample.beans.DerivedTestBean;
2424
import org.springframework.tests.sample.beans.TestBean;
2525

@@ -83,4 +83,22 @@ public void testDisposableBean() {
8383
assertTrue(tb.wasDestroyed());
8484
}
8585

86+
@Test
87+
public void testDependentRegistration() {
88+
DefaultSingletonBeanRegistry beanRegistry = new DefaultSingletonBeanRegistry();
89+
90+
beanRegistry.registerDependentBean("a", "b");
91+
beanRegistry.registerDependentBean("b", "c");
92+
beanRegistry.registerDependentBean("c", "b");
93+
assertTrue(beanRegistry.isDependent("a", "b"));
94+
assertTrue(beanRegistry.isDependent("b", "c"));
95+
assertTrue(beanRegistry.isDependent("c", "b"));
96+
assertTrue(beanRegistry.isDependent("a", "c"));
97+
assertFalse(beanRegistry.isDependent("c", "a"));
98+
assertFalse(beanRegistry.isDependent("b", "a"));
99+
assertFalse(beanRegistry.isDependent("a", "a"));
100+
assertTrue(beanRegistry.isDependent("b", "b"));
101+
assertTrue(beanRegistry.isDependent("c", "c"));
102+
}
103+
86104
}

0 commit comments

Comments
 (0)