revised non-lenient resolution

master
Juergen Hoeller 15 years ago
parent 1d6a7e57c1
commit 3cb073abce
  1. 22
      org.springframework.beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
  2. 12
      org.springframework.context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests-constructorArg.xml
  3. 80
      org.springframework.context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java

@ -220,7 +220,8 @@ class ConstructorResolver {
args = new ArgumentsHolder(explicitArgs);
}
int typeDiffWeight = args.getTypeDifferenceWeight(paramTypes);
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
args.getTypeDifferenceWeight(paramTypes) : args.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
constructorToUse = candidate;
@ -436,8 +437,9 @@ class ConstructorResolver {
args = new ArgumentsHolder(explicitArgs);
}
int typeDiffWeight = args.getTypeDifferenceWeight(paramTypes);
// Choose this constructor if it represents the closest match.
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
args.getTypeDifferenceWeight(paramTypes) : args.getAssignabilityWeight(paramTypes));
// Choose this factory method if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
factoryMethodToUse = candidate;
argsToUse = args.arguments;
@ -744,6 +746,20 @@ class ConstructorResolver {
int rawTypeDiffWeight = MethodInvoker.getTypeDifferenceWeight(paramTypes, this.rawArguments) - 1024;
return (rawTypeDiffWeight < typeDiffWeight ? rawTypeDiffWeight : typeDiffWeight);
}
public int getAssignabilityWeight(Class[] paramTypes) {
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.arguments[i])) {
return Integer.MAX_VALUE;
}
}
for (int i = 0; i < paramTypes.length; i++) {
if (!ClassUtils.isAssignableValue(paramTypes[i], this.rawArguments[i])) {
return Integer.MAX_VALUE - 512;
}
}
return Integer.MAX_VALUE - 1024;
}
}

@ -180,6 +180,18 @@
<constructor-arg index="1"><value>true</value></constructor-arg>
</bean>
<bean id="lenientDependencyTestBean" class="org.springframework.beans.factory.xml.XmlBeanFactoryTests$LenientDependencyTestBean" scope="prototype">
<constructor-arg>
<bean class="org.springframework.beans.DerivedTestBean"/>
</constructor-arg>
</bean>
<bean id="lenientDependencyTestBeanFactoryMethod" class="org.springframework.beans.factory.xml.XmlBeanFactoryTests$LenientDependencyTestBean" scope="prototype" factory-method="create">
<constructor-arg>
<bean class="org.springframework.beans.DerivedTestBean"/>
</constructor-arg>
</bean>
<bean id="string" class="java.lang.String" autowire-candidate="false">
<constructor-arg><value type="java.lang.String">test</value></constructor-arg>
</bean>

@ -1395,6 +1395,48 @@ public final class XmlBeanFactoryTests {
}
}
public @Test void testLenientDependencyMatching() {
XmlBeanFactory xbf = new XmlBeanFactory(CONSTRUCTOR_ARG_CONTEXT);
LenientDependencyTestBean bean = (LenientDependencyTestBean) xbf.getBean("lenientDependencyTestBean");
assertTrue(bean.tb instanceof DerivedTestBean);
}
public @Test void testLenientDependencyMatchingFactoryMethod() {
XmlBeanFactory xbf = new XmlBeanFactory(CONSTRUCTOR_ARG_CONTEXT);
LenientDependencyTestBean bean = (LenientDependencyTestBean) xbf.getBean("lenientDependencyTestBeanFactoryMethod");
assertTrue(bean.tb instanceof DerivedTestBean);
}
public @Test void testNonLenientDependencyMatching() {
XmlBeanFactory xbf = new XmlBeanFactory(CONSTRUCTOR_ARG_CONTEXT);
AbstractBeanDefinition bd = (AbstractBeanDefinition) xbf.getBeanDefinition("lenientDependencyTestBean");
bd.setLenientConstructorResolution(false);
try {
xbf.getBean("lenientDependencyTestBean");
fail("Should have thrown BeanCreationException");
}
catch (BeanCreationException ex) {
// expected
ex.printStackTrace();
assertTrue(ex.getMostSpecificCause().getMessage().contains("Ambiguous"));
}
}
public @Test void testNonLenientDependencyMatchingFactoryMethod() {
XmlBeanFactory xbf = new XmlBeanFactory(CONSTRUCTOR_ARG_CONTEXT);
AbstractBeanDefinition bd = (AbstractBeanDefinition) xbf.getBeanDefinition("lenientDependencyTestBeanFactoryMethod");
bd.setLenientConstructorResolution(false);
try {
xbf.getBean("lenientDependencyTestBeanFactoryMethod");
fail("Should have thrown BeanCreationException");
}
catch (BeanCreationException ex) {
// expected
ex.printStackTrace();
assertTrue(ex.getMostSpecificCause().getMessage().contains("Ambiguous"));
}
}
public @Test void testStringConstructor() {
XmlBeanFactory xbf = new XmlBeanFactory(CONSTRUCTOR_ARG_CONTEXT);
AbstractBeanDefinition bd = (AbstractBeanDefinition) xbf.getBeanDefinition("string");
@ -1425,7 +1467,7 @@ public final class XmlBeanFactoryTests {
fail("Duplicate name not detected");
}
catch (BeansException ex) {
assertTrue(ex.getMessage().indexOf("Bean name 'foo'") > -1);
assertTrue(ex.getMessage().contains("Bean name 'foo'"));
}
}
@ -1435,7 +1477,7 @@ public final class XmlBeanFactoryTests {
fail("Duplicate name not detected");
}
catch (BeansException e) {
assertTrue(e.getMessage().indexOf("Bean name 'foo'") > -1);
assertTrue(e.getMessage().contains("Bean name 'foo'"));
}
}
@ -1658,6 +1700,40 @@ public final class XmlBeanFactoryTests {
}
public static class LenientDependencyTestBean {
public final ITestBean tb;
public LenientDependencyTestBean(ITestBean tb) {
this.tb = tb;
}
public LenientDependencyTestBean(TestBean tb) {
this.tb = tb;
}
public LenientDependencyTestBean(DerivedTestBean tb) {
this.tb = tb;
}
public LenientDependencyTestBean(Map[] m) {
throw new IllegalStateException("Don't pick this constructor");
}
public static LenientDependencyTestBean create(ITestBean tb) {
return new LenientDependencyTestBean(tb);
}
public static LenientDependencyTestBean create(TestBean tb) {
return new LenientDependencyTestBean(tb);
}
public static LenientDependencyTestBean create(DerivedTestBean tb) {
return new LenientDependencyTestBean(tb);
}
}
public static class ConstructorArrayTestBean {
public final Object array;

Loading…
Cancel
Save