From d55af2b445cd3b1c08a7038de4db8e903c36083f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 23 Dec 2014 17:35:11 +0100 Subject: [PATCH] Consistent throwing of last UnsatisfiedDependencyException if available and no constructor resolved Issue: SPR-12543 --- .../factory/support/ConstructorResolver.java | 29 +++++++------- .../DefaultListableBeanFactoryTests.java | 38 ++++++++++++++++++- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java index 5dc6184260..b868471c18 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java @@ -157,7 +157,7 @@ class ConstructorResolver { AutowireUtils.sortConstructors(candidates); int minTypeDiffWeight = Integer.MAX_VALUE; Set> ambiguousConstructors = null; - List causes = null; + LinkedList causes = null; for (int i = 0; i < candidates.length; i++) { Constructor candidate = candidates[i]; @@ -190,22 +190,12 @@ class ConstructorResolver { this.beanFactory.logger.trace( "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex); } - if (i == candidates.length - 1 && constructorToUse == null) { - if (causes != null) { - for (Exception cause : causes) { - this.beanFactory.onSuppressedException(cause); - } - } - throw ex; - } - else { - // Swallow and try next constructor. - if (causes == null) { - causes = new LinkedList(); - } - causes.add(ex); - continue; + // Swallow and try next constructor. + if (causes == null) { + causes = new LinkedList(); } + causes.add(ex); + continue; } } else { @@ -236,6 +226,13 @@ class ConstructorResolver { } if (constructorToUse == null) { + if (causes != null) { + UnsatisfiedDependencyException ex = causes.removeLast(); + for (Exception cause : causes) { + this.beanFactory.onSuppressedException(cause); + } + throw ex; + } throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Could not resolve matching constructor " + "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)"); diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 9fb2285dd3..d60757e6da 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -2023,6 +2023,30 @@ public class DefaultListableBeanFactoryTests { lbf.preInstantiateSingletons(); } + @Test + public void testConstructorDependencyWithClassResolution() { + DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependencyWithClassResolution.class); + bd.getConstructorArgumentValues().addGenericArgumentValue("java.lang.String"); + lbf.registerBeanDefinition("test", bd); + lbf.preInstantiateSingletons(); + } + + @Test + public void testConstructorDependencyWithUnresolvableClass() { + DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); + RootBeanDefinition bd = new RootBeanDefinition(ConstructorDependencyWithClassResolution.class); + bd.getConstructorArgumentValues().addGenericArgumentValue("java.lang.Strin"); + lbf.registerBeanDefinition("test", bd); + try { + lbf.preInstantiateSingletons(); + fail("Should have thrown UnsatisfiedDependencyException"); + } + catch (UnsatisfiedDependencyException expected) { + assertTrue(expected.toString().contains("java.lang.Strin")); + } + } + @Test public void testBeanDefinitionWithInterface() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); @@ -2033,7 +2057,7 @@ public class DefaultListableBeanFactoryTests { } catch (BeanCreationException ex) { assertEquals("test", ex.getBeanName()); - assertTrue(ex.getMessage().toLowerCase().indexOf("interface") != -1); + assertTrue(ex.getMessage().toLowerCase().contains("interface")); } } @@ -2047,7 +2071,7 @@ public class DefaultListableBeanFactoryTests { } catch (BeanCreationException ex) { assertEquals("test", ex.getBeanName()); - assertTrue(ex.getMessage().toLowerCase().indexOf("abstract") != -1); + assertTrue(ex.getMessage().toLowerCase().contains("abstract")); } } @@ -2739,6 +2763,16 @@ public class DefaultListableBeanFactoryTests { } + public static class ConstructorDependencyWithClassResolution { + + public ConstructorDependencyWithClassResolution(Class clazz) { + } + + public ConstructorDependencyWithClassResolution() { + } + } + + public static class BeanWithDisposableBean implements DisposableBean { private static boolean closed;