Skip to content

Commit c9d3c26

Browse files
committed
Properly resolve null candidates for collection injection
Issue: SPR-16033
1 parent 30d1b53 commit c9d3c26

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,8 @@ private void addCandidateEntry(Map<String, Object> candidates, String candidateN
13171317
DependencyDescriptor descriptor, Class<?> requiredType) {
13181318

13191319
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
1320-
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
1320+
Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this);
1321+
candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance));
13211322
}
13221323
else {
13231324
candidates.put(candidateName, getType(candidateName));

spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,29 @@ public void testConstructorResourceInjectionWithNoCandidatesAndNoFallback() {
681681
}
682682
}
683683

684+
@Test
685+
public void testConstructorResourceInjectionWithCollectionAndNullFromFactoryBean() {
686+
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
687+
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
688+
bpp.setBeanFactory(bf);
689+
bf.addBeanPostProcessor(bpp);
690+
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(
691+
ConstructorsCollectionResourceInjectionBean.class));
692+
TestBean tb = new TestBean();
693+
bf.registerSingleton("testBean", tb);
694+
bf.registerBeanDefinition("nestedTestBean1", new RootBeanDefinition(NullNestedTestBeanFactoryBean.class));
695+
NestedTestBean ntb2 = new NestedTestBean();
696+
bf.registerSingleton("nestedTestBean2", ntb2);
697+
698+
ConstructorsCollectionResourceInjectionBean bean = (ConstructorsCollectionResourceInjectionBean) bf.getBean("annotatedBean");
699+
assertNull(bean.getTestBean3());
700+
assertSame(tb, bean.getTestBean4());
701+
assertEquals(2, bean.getNestedTestBeans().size());
702+
assertNull(bean.getNestedTestBeans().get(0));
703+
assertSame(ntb2, bean.getNestedTestBeans().get(1));
704+
bf.destroySingletons();
705+
}
706+
684707
@Test
685708
public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() {
686709
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
@@ -860,23 +883,20 @@ public void testConstructorInjectionWithMap() {
860883
bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE);
861884
bf.registerBeanDefinition("annotatedBean", bd);
862885
TestBean tb1 = new TestBean("tb1");
863-
TestBean tb2 = new TestBean("tb2");
864886
bf.registerSingleton("testBean1", tb1);
865-
bf.registerSingleton("testBean2", tb2);
887+
RootBeanDefinition tb2 = new RootBeanDefinition(NullFactoryMethods.class);
888+
tb2.setFactoryMethodName("createTestBean");
889+
bf.registerBeanDefinition("testBean2", tb2);
866890

867891
MapConstructorInjectionBean bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
868892
assertEquals(2, bean.getTestBeanMap().size());
869-
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
870-
assertTrue(bean.getTestBeanMap().keySet().contains("testBean2"));
871-
assertTrue(bean.getTestBeanMap().values().contains(tb1));
872-
assertTrue(bean.getTestBeanMap().values().contains(tb2));
893+
assertSame(tb1, bean.getTestBeanMap().get("testBean1"));
894+
assertNull(bean.getTestBeanMap().get("testBean2"));
873895

874896
bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean");
875897
assertEquals(2, bean.getTestBeanMap().size());
876-
assertTrue(bean.getTestBeanMap().keySet().contains("testBean1"));
877-
assertTrue(bean.getTestBeanMap().keySet().contains("testBean2"));
878-
assertTrue(bean.getTestBeanMap().values().contains(tb1));
879-
assertTrue(bean.getTestBeanMap().values().contains(tb2));
898+
assertSame(tb1, bean.getTestBeanMap().get("testBean1"));
899+
assertNull(bean.getTestBeanMap().get("testBean2"));
880900
}
881901

882902
@Test

0 commit comments

Comments
 (0)