From c9d3c2690d5010f6cafe8fb98ae8e9c0b6d92d9b Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 2 Oct 2017 12:27:11 +0200 Subject: [PATCH] Properly resolve null candidates for collection injection Issue: SPR-16033 --- .../support/DefaultListableBeanFactory.java | 3 +- ...wiredAnnotationBeanPostProcessorTests.java | 40 ++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java index 1cf6b17ff5..4d4ef662c5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java @@ -1317,7 +1317,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto DependencyDescriptor descriptor, Class requiredType) { if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) { - candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this)); + Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this); + candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { candidates.put(candidateName, getType(candidateName)); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java index 635883fa92..da27d15171 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java @@ -681,6 +681,29 @@ public class AutowiredAnnotationBeanPostProcessorTests { } } + @Test + public void testConstructorResourceInjectionWithCollectionAndNullFromFactoryBean() { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); + bpp.setBeanFactory(bf); + bf.addBeanPostProcessor(bpp); + bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition( + ConstructorsCollectionResourceInjectionBean.class)); + TestBean tb = new TestBean(); + bf.registerSingleton("testBean", tb); + bf.registerBeanDefinition("nestedTestBean1", new RootBeanDefinition(NullNestedTestBeanFactoryBean.class)); + NestedTestBean ntb2 = new NestedTestBean(); + bf.registerSingleton("nestedTestBean2", ntb2); + + ConstructorsCollectionResourceInjectionBean bean = (ConstructorsCollectionResourceInjectionBean) bf.getBean("annotatedBean"); + assertNull(bean.getTestBean3()); + assertSame(tb, bean.getTestBean4()); + assertEquals(2, bean.getNestedTestBeans().size()); + assertNull(bean.getNestedTestBeans().get(0)); + assertSame(ntb2, bean.getNestedTestBeans().get(1)); + bf.destroySingletons(); + } + @Test public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); @@ -860,23 +883,20 @@ public class AutowiredAnnotationBeanPostProcessorTests { bd.setScope(RootBeanDefinition.SCOPE_PROTOTYPE); bf.registerBeanDefinition("annotatedBean", bd); TestBean tb1 = new TestBean("tb1"); - TestBean tb2 = new TestBean("tb2"); bf.registerSingleton("testBean1", tb1); - bf.registerSingleton("testBean2", tb2); + RootBeanDefinition tb2 = new RootBeanDefinition(NullFactoryMethods.class); + tb2.setFactoryMethodName("createTestBean"); + bf.registerBeanDefinition("testBean2", tb2); MapConstructorInjectionBean bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean"); assertEquals(2, bean.getTestBeanMap().size()); - assertTrue(bean.getTestBeanMap().keySet().contains("testBean1")); - assertTrue(bean.getTestBeanMap().keySet().contains("testBean2")); - assertTrue(bean.getTestBeanMap().values().contains(tb1)); - assertTrue(bean.getTestBeanMap().values().contains(tb2)); + assertSame(tb1, bean.getTestBeanMap().get("testBean1")); + assertNull(bean.getTestBeanMap().get("testBean2")); bean = (MapConstructorInjectionBean) bf.getBean("annotatedBean"); assertEquals(2, bean.getTestBeanMap().size()); - assertTrue(bean.getTestBeanMap().keySet().contains("testBean1")); - assertTrue(bean.getTestBeanMap().keySet().contains("testBean2")); - assertTrue(bean.getTestBeanMap().values().contains(tb1)); - assertTrue(bean.getTestBeanMap().values().contains(tb2)); + assertSame(tb1, bean.getTestBeanMap().get("testBean1")); + assertNull(bean.getTestBeanMap().get("testBean2")); } @Test