Prevent ValueBinder from being incorrectly used

Fix a regression caused by e41c5a43 which incorrectly allowed the
`ValueObjectBinder` to be picked when the `JavaBeanBinder` should
have been used.

Closes gh-18485
pull/18490/head
Phillip Webb 5 years ago
parent 5547a8499f
commit b1f23f54df

@ -203,13 +203,12 @@ class ValueObjectBinder implements DataObjectBinder {
constructor = candidate;
}
}
return (constructor != null) ? new DefaultValueObject<>((Constructor<T>) constructor) : null;
return get((Constructor<T>) constructor);
}
private static boolean isCandidateConstructor(Constructor<?> candidate, Predicate<Constructor<?>> filter) {
int modifiers = candidate.getModifiers();
return !Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers)
&& candidate.getParameterCount() > 0 && filter.test(candidate);
return !Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers) && filter.test(candidate);
}
static <T> DefaultValueObject<T> get(Constructor<T> constructor) {

@ -807,6 +807,35 @@ class ConfigurationPropertiesTests {
assertThat(bean.getNested().getAge()).isEqualTo(5);
}
@Test // gh-18485
void loadWhenBindingToMultiConstructorConfigurationProperties() {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new HashMap<>();
source.put("test.nested[0].name", "spring");
source.put("test.nested[0].age", "5");
sources.addLast(new MapPropertySource("test", source));
load(MultiConstructorConfigurationPropertiesConfiguration.class);
MultiConstructorConfigurationListProperties bean = this.context
.getBean(MultiConstructorConfigurationListProperties.class);
MultiConstructorConfigurationProperties nested = bean.getNested().get(0);
assertThat(nested.getName()).isEqualTo("spring");
assertThat(nested.getAge()).isEqualTo(5);
}
@Test // gh-18485
void loadWhenBindingToMultiConstructorConfigurationPropertiesUsingShortcutSyntax() {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new HashMap<>();
source.put("test.nested[0]", "spring");
sources.addLast(new MapPropertySource("test", source));
load(MultiConstructorConfigurationPropertiesConfiguration.class);
MultiConstructorConfigurationListProperties bean = this.context
.getBean(MultiConstructorConfigurationListProperties.class);
MultiConstructorConfigurationProperties nested = bean.getNested().get(0);
assertThat(nested.getName()).isEqualTo("spring");
assertThat(nested.getAge()).isEqualTo(0);
}
private AnnotationConfigApplicationContext load(Class<?> configuration, String... inlinedProperties) {
return load(new Class<?>[] { configuration }, inlinedProperties);
}
@ -1968,4 +1997,21 @@ class ConfigurationPropertiesTests {
}
@ConfigurationProperties("test")
static class MultiConstructorConfigurationListProperties {
private List<MultiConstructorConfigurationProperties> nested = new ArrayList<>();
List<MultiConstructorConfigurationProperties> getNested() {
return this.nested;
}
}
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(MultiConstructorConfigurationListProperties.class)
static class MultiConstructorConfigurationPropertiesConfiguration {
}
}

@ -0,0 +1,54 @@
/*
* Copyright 2012-2019 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.context.properties;
/**
* Class used to test multi-constructor binding. Must be public and have public
* constructors.
*
* @author Phillip Webb
*/
public class MultiConstructorConfigurationProperties {
private String name;
private int age;
public MultiConstructorConfigurationProperties() {
}
public MultiConstructorConfigurationProperties(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
Loading…
Cancel
Save