Skip to content

Commit 547b963

Browse files
committed
Collection injection may refer back to factory methods on same bean again
Issue: SPR-14996
1 parent aa29495 commit 547b963

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

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

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,7 @@ private Object resolveMultipleBeans(DependencyDescriptor descriptor, String bean
11371137
if (type.isArray()) {
11381138
Class<?> componentType = type.getComponentType();
11391139
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
1140-
new MultiElementDependencyDescriptor(descriptor));
1140+
new MultiElementDescriptor(descriptor));
11411141
if (matchingBeans.isEmpty()) {
11421142
return null;
11431143
}
@@ -1157,7 +1157,7 @@ else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
11571157
return null;
11581158
}
11591159
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
1160-
new MultiElementDependencyDescriptor(descriptor));
1160+
new MultiElementDescriptor(descriptor));
11611161
if (matchingBeans.isEmpty()) {
11621162
return null;
11631163
}
@@ -1181,7 +1181,7 @@ else if (Map.class.isAssignableFrom(type) && type.isInterface()) {
11811181
return null;
11821182
}
11831183
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
1184-
new MultiElementDependencyDescriptor(descriptor));
1184+
new MultiElementDescriptor(descriptor));
11851185
if (matchingBeans.isEmpty()) {
11861186
return null;
11871187
}
@@ -1248,25 +1248,27 @@ protected Map<String, Object> findAutowireCandidates(
12481248
}
12491249
}
12501250
}
1251-
for (String candidateName : candidateNames) {
1252-
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) {
1253-
addCandidateEntry(result, candidateName, descriptor, requiredType);
1251+
for (String candidate : candidateNames) {
1252+
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
1253+
addCandidateEntry(result, candidate, descriptor, requiredType);
12541254
}
12551255
}
12561256
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
12571257
// Consider fallback matches if the first pass failed to find anything...
12581258
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
1259-
for (String candidateName : candidateNames) {
1260-
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
1261-
addCandidateEntry(result, candidateName, descriptor, requiredType);
1259+
for (String candidate : candidateNames) {
1260+
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
1261+
addCandidateEntry(result, candidate, descriptor, requiredType);
12621262
}
12631263
}
1264-
if (result.isEmpty() && !(descriptor instanceof MultiElementDependencyDescriptor)) {
1264+
if (result.isEmpty()) {
12651265
// Consider self references as a final pass...
1266-
// but not as collection elements, just for direct dependency declarations.
1267-
for (String candidateName : candidateNames) {
1268-
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) {
1269-
addCandidateEntry(result, candidateName, descriptor, requiredType);
1266+
// but in the case of a dependency collection, not the very same bean itself.
1267+
for (String candidate : candidateNames) {
1268+
if (isSelfReference(beanName, candidate) &&
1269+
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
1270+
isAutowireCandidate(candidate, fallbackDescriptor)) {
1271+
addCandidateEntry(result, candidate, descriptor, requiredType);
12701272
}
12711273
}
12721274
}
@@ -1281,7 +1283,7 @@ protected Map<String, Object> findAutowireCandidates(
12811283
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
12821284
DependencyDescriptor descriptor, Class<?> requiredType) {
12831285

1284-
if (descriptor instanceof MultiElementDependencyDescriptor || containsSingleton(candidateName)) {
1286+
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
12851287
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
12861288
}
12871289
else {
@@ -1730,9 +1732,9 @@ public NestedDependencyDescriptor(DependencyDescriptor original) {
17301732
}
17311733

17321734

1733-
private static class MultiElementDependencyDescriptor extends NestedDependencyDescriptor {
1735+
private static class MultiElementDescriptor extends NestedDependencyDescriptor {
17341736

1735-
public MultiElementDependencyDescriptor(DependencyDescriptor original) {
1737+
public MultiElementDescriptor(DependencyDescriptor original) {
17361738
super(original);
17371739
}
17381740
}

spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.lang.annotation.Retention;
2121
import java.lang.annotation.RetentionPolicy;
2222
import java.lang.annotation.Target;
23+
import java.util.List;
2324
import javax.annotation.PostConstruct;
2425

2526
import org.junit.Before;
@@ -615,6 +616,15 @@ public void testInjectionPointMatchForNarrowTargetReturnType() {
615616
assertSame(ctx.getBean(BarImpl.class), ctx.getBean(FooImpl.class).bar);
616617
}
617618

619+
@Test
620+
public void testCollectionInjectionFromSameConfigurationClass() {
621+
ApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionInjectionConfiguration.class);
622+
CollectionInjectionConfiguration bean = ctx.getBean(CollectionInjectionConfiguration.class);
623+
assertNotNull(bean.testBeans);
624+
assertEquals(1, bean.testBeans.size());
625+
assertSame(ctx.getBean(TestBean.class), bean.testBeans.get(0));
626+
}
627+
618628

619629
// -------------------------------------------------------------------------
620630

@@ -1253,4 +1263,16 @@ public BarInterface bar() {
12531263
}
12541264
}
12551265

1266+
@Configuration
1267+
static class CollectionInjectionConfiguration {
1268+
1269+
@Autowired(required = false)
1270+
public List<TestBean> testBeans;
1271+
1272+
@Bean
1273+
public TestBean thing() {
1274+
return new TestBean();
1275+
}
1276+
}
1277+
12561278
}

0 commit comments

Comments
 (0)