Browse Source

Collection injection may refer back to factory methods on same bean again

Issue: SPR-14996
pull/1153/merge
Juergen Hoeller 9 years ago
parent
commit
547b9638dc
  1. 36
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java
  2. 22
      spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java

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

@ -1137,7 +1137,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (type.isArray()) { if (type.isArray()) {
Class<?> componentType = type.getComponentType(); Class<?> componentType = type.getComponentType();
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDependencyDescriptor(descriptor)); new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) { if (matchingBeans.isEmpty()) {
return null; return null;
} }
@ -1157,7 +1157,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null; return null;
} }
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDependencyDescriptor(descriptor)); new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) { if (matchingBeans.isEmpty()) {
return null; return null;
} }
@ -1181,7 +1181,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
return null; return null;
} }
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDependencyDescriptor(descriptor)); new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) { if (matchingBeans.isEmpty()) {
return null; return null;
} }
@ -1248,25 +1248,27 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
} }
} }
for (String candidateName : candidateNames) { for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, descriptor)) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
addCandidateEntry(result, candidateName, descriptor, requiredType); addCandidateEntry(result, candidate, descriptor, requiredType);
} }
} }
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) { if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
// Consider fallback matches if the first pass failed to find anything... // Consider fallback matches if the first pass failed to find anything...
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch(); DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidateName : candidateNames) { for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidateName, descriptor, requiredType); addCandidateEntry(result, candidate, descriptor, requiredType);
} }
} }
if (result.isEmpty() && !(descriptor instanceof MultiElementDependencyDescriptor)) { if (result.isEmpty()) {
// Consider self references as a final pass... // Consider self references as a final pass...
// but not as collection elements, just for direct dependency declarations. // but in the case of a dependency collection, not the very same bean itself.
for (String candidateName : candidateNames) { for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidateName) && isAutowireCandidate(candidateName, fallbackDescriptor)) { if (isSelfReference(beanName, candidate) &&
addCandidateEntry(result, candidateName, descriptor, requiredType); (!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
} }
} }
} }
@ -1281,7 +1283,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
private void addCandidateEntry(Map<String, Object> candidates, String candidateName, private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) { DependencyDescriptor descriptor, Class<?> requiredType) {
if (descriptor instanceof MultiElementDependencyDescriptor || containsSingleton(candidateName)) { if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this)); candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
} }
else { else {
@ -1730,9 +1732,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
} }
private static class MultiElementDependencyDescriptor extends NestedDependencyDescriptor { private static class MultiElementDescriptor extends NestedDependencyDescriptor {
public MultiElementDependencyDescriptor(DependencyDescriptor original) { public MultiElementDescriptor(DependencyDescriptor original) {
super(original); super(original);
} }
} }

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

@ -20,6 +20,7 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.List;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.junit.Before; import org.junit.Before;
@ -615,6 +616,15 @@ public class ConfigurationClassPostProcessorTests {
assertSame(ctx.getBean(BarImpl.class), ctx.getBean(FooImpl.class).bar); assertSame(ctx.getBean(BarImpl.class), ctx.getBean(FooImpl.class).bar);
} }
@Test
public void testCollectionInjectionFromSameConfigurationClass() {
ApplicationContext ctx = new AnnotationConfigApplicationContext(CollectionInjectionConfiguration.class);
CollectionInjectionConfiguration bean = ctx.getBean(CollectionInjectionConfiguration.class);
assertNotNull(bean.testBeans);
assertEquals(1, bean.testBeans.size());
assertSame(ctx.getBean(TestBean.class), bean.testBeans.get(0));
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -1253,4 +1263,16 @@ public class ConfigurationClassPostProcessorTests {
} }
} }
@Configuration
static class CollectionInjectionConfiguration {
@Autowired(required = false)
public List<TestBean> testBeans;
@Bean
public TestBean thing() {
return new TestBean();
}
}
} }

Loading…
Cancel
Save