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 0e6aa32702..5ede49dcd2 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 @@ -523,24 +523,30 @@ class ConstructorResolver { } if (factoryMethodToUse == null) { - boolean hasArgs = (resolvedValues.getArgumentCount() > 0); - String argDesc = ""; - if (hasArgs) { - List argTypes = new ArrayList(); - for (ValueHolder value : resolvedValues.getIndexedArgumentValues().values()) { - String argType = (value.getType() != null ? - ClassUtils.getShortName(value.getType()) : value.getValue().getClass().getSimpleName()); + List argTypes = new ArrayList(minNrOfArgs); + if (explicitArgs != null) { + for (Object arg : explicitArgs) { + argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null"); + } + } + else { + Set valueHolders = new LinkedHashSet(resolvedValues.getArgumentCount()); + valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values()); + valueHolders.addAll(resolvedValues.getGenericArgumentValues()); + for (ValueHolder value : valueHolders) { + String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) : + (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null")); argTypes.add(argType); } - argDesc = StringUtils.collectionToCommaDelimitedString(argTypes); } + String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes); throw new BeanCreationException(mbd.getResourceDescription(), beanName, "No matching factory method found: " + (mbd.getFactoryBeanName() != null ? "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") + "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " + "Check that a method with the specified name " + - (hasArgs ? "and arguments " : "") + + (minNrOfArgs > 0 ? "and arguments " : "") + "exists and that it is " + (isStatic ? "static" : "non-static") + "."); } diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java index 0d67448bc0..c1ab301059 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/xml/FactoryMethodTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ import java.util.Collections; import java.util.List; import java.util.Properties; -import static org.junit.Assert.*; import org.junit.Test; import org.springframework.beans.factory.BeanCreationException; @@ -30,6 +29,8 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.tests.sample.beans.TestBean; +import static org.junit.Assert.*; + /** * @author Juergen Hoeller * @author Chris Beams @@ -259,6 +260,34 @@ public class FactoryMethodTests { } } + @Test + public void testNonExistingFactoryMethod() { + DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); + reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass())); + try { + xbf.getBean("invalidPrototype"); + fail("Should have thrown BeanCreationException"); + } + catch (BeanCreationException ex) { + assertTrue(ex.getMessage().contains("nonExisting(TestBean)")); + } + } + + @Test + public void testFactoryMethodArgumentsForNonExistingMethod() { + DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); + XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(xbf); + reader.loadBeanDefinitions(new ClassPathResource("factory-methods.xml", getClass())); + try { + xbf.getBean("invalidPrototype", new TestBean()); + fail("Should have thrown BeanCreationException"); + } + catch (BeanCreationException ex) { + assertTrue(ex.getMessage().contains("nonExisting(TestBean)")); + } + } + @Test public void testCanSpecifyFactoryMethodArgumentsOnFactoryMethodPrototype() { DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); @@ -360,7 +389,9 @@ public class FactoryMethodTests { } + class MailSession { + private Properties props; private MailSession() { @@ -377,6 +408,6 @@ class MailSession { } public Object getProperty(String key) { - return props.get(key); + return this.props.get(key); } } diff --git a/spring-beans/src/test/resources/org/springframework/beans/factory/xml/factory-methods.xml b/spring-beans/src/test/resources/org/springframework/beans/factory/xml/factory-methods.xml index 4ff20b3d59..ffcd3f7da9 100644 --- a/spring-beans/src/test/resources/org/springframework/beans/factory/xml/factory-methods.xml +++ b/spring-beans/src/test/resources/org/springframework/beans/factory/xml/factory-methods.xml @@ -84,6 +84,11 @@ testBeanOnlyPrototypeDISetterString + + + + 27 @@ -120,9 +125,7 @@ 33 - +