revised non-lenient resolution
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user