Browse Source

Leniently allow constructor argument matches if required name is not resolvable

Issue: SPR-13987
pull/909/merge
Juergen Hoeller 9 years ago
parent
commit
431ca9314a
  1. 12
      spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java
  2. 2
      spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
  3. 4
      spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java
  4. 4
      spring-context/src/test/resources/org/springframework/beans/factory/xml/XmlBeanFactoryTests-constructorArg.xml

12
spring-beans/src/main/java/org/springframework/beans/factory/config/ConstructorArgumentValues.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -156,7 +156,7 @@ public class ConstructorArgumentValues {
* @param requiredType the type to match (can be {@code null} to match * @param requiredType the type to match (can be {@code null} to match
* untyped values only) * untyped values only)
* @param requiredName the type to match (can be {@code null} to match * @param requiredName the type to match (can be {@code null} to match
* unnamed values only) * unnamed values only, or empty String to match any name)
* @return the ValueHolder for the argument, or {@code null} if none set * @return the ValueHolder for the argument, or {@code null} if none set
*/ */
public ValueHolder getIndexedArgumentValue(int index, Class<?> requiredType, String requiredName) { public ValueHolder getIndexedArgumentValue(int index, Class<?> requiredType, String requiredName) {
@ -165,7 +165,7 @@ public class ConstructorArgumentValues {
if (valueHolder != null && if (valueHolder != null &&
(valueHolder.getType() == null || (valueHolder.getType() == null ||
(requiredType != null && ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) && (requiredType != null && ClassUtils.matchesTypeName(requiredType, valueHolder.getType()))) &&
(valueHolder.getName() == null || (valueHolder.getName() == null || "".equals(requiredName) ||
(requiredName != null && requiredName.equals(valueHolder.getName())))) { (requiredName != null && requiredName.equals(valueHolder.getName())))) {
return valueHolder; return valueHolder;
} }
@ -268,7 +268,7 @@ public class ConstructorArgumentValues {
* @param requiredType the type to match (can be {@code null} to find * @param requiredType the type to match (can be {@code null} to find
* an arbitrary next generic argument value) * an arbitrary next generic argument value)
* @param requiredName the name to match (can be {@code null} to not * @param requiredName the name to match (can be {@code null} to not
* match argument values by name) * match argument values by name, or empty String to match any name)
* @param usedValueHolders a Set of ValueHolder objects that have already been used * @param usedValueHolders a Set of ValueHolder objects that have already been used
* in the current resolution process and should therefore not be returned again * in the current resolution process and should therefore not be returned again
* @return the ValueHolder for the argument, or {@code null} if none found * @return the ValueHolder for the argument, or {@code null} if none found
@ -278,7 +278,7 @@ public class ConstructorArgumentValues {
if (usedValueHolders != null && usedValueHolders.contains(valueHolder)) { if (usedValueHolders != null && usedValueHolders.contains(valueHolder)) {
continue; continue;
} }
if (valueHolder.getName() != null && if (valueHolder.getName() != null && !"".equals(requiredName) &&
(requiredName == null || !valueHolder.getName().equals(requiredName))) { (requiredName == null || !valueHolder.getName().equals(requiredName))) {
continue; continue;
} }
@ -335,7 +335,7 @@ public class ConstructorArgumentValues {
* @param requiredType the parameter type to match (can be {@code null} * @param requiredType the parameter type to match (can be {@code null}
* to find an untyped argument value) * to find an untyped argument value)
* @param requiredName the parameter name to match (can be {@code null} * @param requiredName the parameter name to match (can be {@code null}
* to find an unnamed argument value) * to find an unnamed argument value, or empty String to match any name)
* @param usedValueHolders a Set of ValueHolder objects that have already * @param usedValueHolders a Set of ValueHolder objects that have already
* been used in the current resolution process and should therefore not * been used in the current resolution process and should therefore not
* be returned again (allowing to return the next generic argument match * be returned again (allowing to return the next generic argument match

2
spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java

@ -675,7 +675,7 @@ class ConstructorResolver {
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) { for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
Class<?> paramType = paramTypes[paramIndex]; Class<?> paramType = paramTypes[paramIndex];
String paramName = (paramNames != null ? paramNames[paramIndex] : null); String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic. // Try to find matching constructor argument value, either indexed or generic.
ConstructorArgumentValues.ValueHolder valueHolder = ConstructorArgumentValues.ValueHolder valueHolder =
resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders); resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);

4
spring-context/src/test/java/org/springframework/beans/factory/xml/XmlBeanFactoryTests.java

@ -1612,12 +1612,14 @@ public class XmlBeanFactoryTests {
assertEquals(0, ((String[]) bean.array).length); assertEquals(0, ((String[]) bean.array).length);
} }
@Test @Ignore // TODO: SPR-13987 @Test
public void testConstructorWithUnresolvableParameterName() { public void testConstructorWithUnresolvableParameterName() {
DefaultListableBeanFactory xbf = new DefaultListableBeanFactory(); DefaultListableBeanFactory xbf = new DefaultListableBeanFactory();
new XmlBeanDefinitionReader(xbf).loadBeanDefinitions(CONSTRUCTOR_ARG_CONTEXT); new XmlBeanDefinitionReader(xbf).loadBeanDefinitions(CONSTRUCTOR_ARG_CONTEXT);
AtomicInteger bean = (AtomicInteger) xbf.getBean("constructorUnresolvableName"); AtomicInteger bean = (AtomicInteger) xbf.getBean("constructorUnresolvableName");
assertEquals(1, bean.get()); assertEquals(1, bean.get());
bean = (AtomicInteger) xbf.getBean("constructorUnresolvableNameWithIndex");
assertEquals(1, bean.get());
} }
@Test @Test

4
spring-context/src/test/resources/org/springframework/beans/factory/xml/XmlBeanFactoryTests-constructorArg.xml

@ -231,4 +231,8 @@
<constructor-arg name="initialValue" value="1"/> <constructor-arg name="initialValue" value="1"/>
</bean> </bean>
<bean id="constructorUnresolvableNameWithIndex" class="java.util.concurrent.atomic.AtomicInteger" scope="prototype">
<constructor-arg index="0" name="initialValue" value="1"/>
</bean>
</beans> </beans>

Loading…
Cancel
Save