Browse Source

Import ConstructorResolver to handle null values

Previously, ConstructorResolver would reject any candidate if the
parameter is `null`. The reason for that is that null does not carry
any type and the matching algorithm would systematically fail for that
argument.

This commit adds an extra check, and several tests, to validate that
a null value is taken into account.

Closes gh-31495
pull/31518/head
Stéphane Nicoll 2 years ago
parent
commit
4977ef9cea
  1. 3
      spring-beans/src/main/java/org/springframework/beans/factory/support/ConstructorResolver.java
  2. 46
      spring-beans/src/test/java/org/springframework/beans/factory/support/ConstructorResolverAotTests.java

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

@ -1200,7 +1200,8 @@ class ConstructorResolver { @@ -1200,7 +1200,8 @@ class ConstructorResolver {
}
private Predicate<ResolvableType> isAssignable(ResolvableType valueType) {
return parameterType -> parameterType.isAssignableFrom(valueType);
return parameterType -> (valueType == ResolvableType.NONE
|| parameterType.isAssignableFrom(valueType));
}
private ResolvableType extractElementType(ResolvableType parameterType) {

46
spring-beans/src/test/java/org/springframework/beans/factory/support/ConstructorResolverAotTests.java

@ -414,6 +414,43 @@ class ConstructorResolverAotTests { @@ -414,6 +414,43 @@ class ConstructorResolverAotTests {
String[].class));
}
@Test
void beanDefinitionWithMultiConstructorSimilarArgumentsAndMatchingValues() throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSimilarArgumentsSample.class)
.addConstructorArgValue("Test").addConstructorArgValue(1).addConstructorArgValue(2)
.getBeanDefinition();
Executable executable = resolve(beanFactory, beanDefinition);
assertThat(executable).isNotNull()
.isEqualTo(MultiConstructorSimilarArgumentsSample.class
.getDeclaredConstructor(String.class, Integer.class, Integer.class));
}
@Test
void beanDefinitionWithMultiConstructorSimilarArgumentsAndNullValueForCommonArgument() throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSimilarArgumentsSample.class)
.addConstructorArgValue(null).addConstructorArgValue(null).addConstructorArgValue("Test")
.getBeanDefinition();
Executable executable = resolve(beanFactory, beanDefinition);
assertThat(executable).isNotNull()
.isEqualTo(MultiConstructorSimilarArgumentsSample.class
.getDeclaredConstructor(String.class, Integer.class, String.class));
}
@Test
void beanDefinitionWithMultiConstructorSimilarArgumentsAndNullValueForSpecificArgument() throws NoSuchMethodException {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(MultiConstructorSimilarArgumentsSample.class)
.addConstructorArgValue(null).addConstructorArgValue(1).addConstructorArgValue(null)
.getBeanDefinition();
assertThatIllegalStateException().isThrownBy(() -> resolve(beanFactory, beanDefinition))
.withMessageContaining(MultiConstructorSimilarArgumentsSample.class.getName());
}
@Test
void beanDefinitionWithMultiArgConstructorAndPrimitiveConversion() throws NoSuchMethodException {
BeanDefinition beanDefinition = BeanDefinitionBuilder
@ -534,6 +571,15 @@ class ConstructorResolverAotTests { @@ -534,6 +571,15 @@ class ConstructorResolverAotTests {
}
}
static class MultiConstructorSimilarArgumentsSample {
MultiConstructorSimilarArgumentsSample(String name, Integer counter, String value) {
}
MultiConstructorSimilarArgumentsSample(String name, Integer counter, Integer value) {
}
}
@SuppressWarnings("unused")
static class ClassArrayFactoryMethodSample {

Loading…
Cancel
Save