From 5cf452463eeb3f2a230319c6a40a2c0f67e49be3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 17 Sep 2014 13:35:12 +0200 Subject: [PATCH] Log warning for single optional constructor when no default constructor to fall back to Issue: SPR-12161 (cherry picked from commit 80cec01) --- .../AutowiredAnnotationBeanPostProcessor.java | 12 +++++-- ...wiredAnnotationBeanPostProcessorTests.java | 34 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java index 811ee97daeb..bc7e56b60be 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java @@ -263,8 +263,16 @@ public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBean } if (!candidates.isEmpty()) { // Add default constructor to list of optional constructors, as fallback. - if (requiredConstructor == null && defaultConstructor != null) { - candidates.add(defaultConstructor); + if (requiredConstructor == null) { + if (defaultConstructor != null) { + candidates.add(defaultConstructor); + } + else if (candidates.size() == 1 && logger.isWarnEnabled()) { + logger.warn("Inconsistent constructor declaration on bean with name '" + beanName + + "': single autowire-marked constructor flagged as optional - this constructor " + + "is effectively required since there is no default constructor to fall back to: " + + candidates.get(0)); + } } candidateConstructors = candidates.toArray(new Constructor[candidates.size()]); } 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 9f91ae11a04..dc2e7bdf330 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 @@ -30,6 +30,7 @@ import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.UnsatisfiedDependencyException; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.AutowireCandidateQualifier; @@ -395,6 +396,23 @@ public class AutowiredAnnotationBeanPostProcessorTests { bf.destroySingletons(); } + @Test + public void testConstructorResourceInjectionWithNoCandidatesAndNoFallback() { + DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); + AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); + bpp.setBeanFactory(bf); + bf.addBeanPostProcessor(bpp); + bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(ConstructorWithoutFallbackBean.class)); + + try { + bf.getBean("annotatedBean"); + fail("Should have thrown UnsatisfiedDependencyException"); + } + catch (UnsatisfiedDependencyException ex) { + // expected + } + } + @Test public void testConstructorResourceInjectionWithMultipleCandidatesAsCollection() { DefaultListableBeanFactory bf = new DefaultListableBeanFactory(); @@ -1256,6 +1274,21 @@ public class AutowiredAnnotationBeanPostProcessorTests { } + public static class ConstructorWithoutFallbackBean { + + protected ITestBean testBean3; + + @Autowired(required = false) + public ConstructorWithoutFallbackBean(ITestBean testBean3) { + this.testBean3 = testBean3; + } + + public ITestBean getTestBean3() { + return this.testBean3; + } + } + + public static class ConstructorsCollectionResourceInjectionBean { protected ITestBean testBean3; @@ -1321,7 +1354,6 @@ public class AutowiredAnnotationBeanPostProcessorTests { @Autowired private Map testBeanMap; - public Map getTestBeanMap() { return this.testBeanMap; }