commit
9486842bad
|
@ -36,6 +36,7 @@ import org.springframework.core.KotlinDetector;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.core.ParameterNameDiscoverer;
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
|
import org.springframework.core.convert.ConversionException;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,16 +95,30 @@ class ValueObjectBinder implements DataObjectBinder {
|
||||||
Annotation[] annotations = parameter.getAnnotations();
|
Annotation[] annotations = parameter.getAnnotations();
|
||||||
for (Annotation annotation : annotations) {
|
for (Annotation annotation : annotations) {
|
||||||
if (annotation instanceof DefaultValue) {
|
if (annotation instanceof DefaultValue) {
|
||||||
DefaultValue defaultValue = (DefaultValue) annotation;
|
String[] defaultValue = ((DefaultValue) annotation).value();
|
||||||
if (defaultValue.value().length == 0) {
|
if (defaultValue.length == 0) {
|
||||||
return getNewInstanceIfPossible(context, type);
|
return getNewInstanceIfPossible(context, type);
|
||||||
}
|
}
|
||||||
return context.getConverter().convert(defaultValue.value(), type, annotations);
|
return convertDefaultValue(context.getConverter(), defaultValue, type, annotations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T convertDefaultValue(BindConverter converter, String[] defaultValue, ResolvableType type,
|
||||||
|
Annotation[] annotations) {
|
||||||
|
try {
|
||||||
|
return converter.convert(defaultValue, type, annotations);
|
||||||
|
}
|
||||||
|
catch (ConversionException ex) {
|
||||||
|
// Try again in case ArrayToObjectConverter is not in play
|
||||||
|
if (defaultValue.length == 1) {
|
||||||
|
return converter.convert(defaultValue[0], type, annotations);
|
||||||
|
}
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T> T getNewInstanceIfPossible(Binder.Context context, ResolvableType type) {
|
private <T> T getNewInstanceIfPossible(Binder.Context context, ResolvableType type) {
|
||||||
Class<T> resolved = (Class<T>) type.resolve();
|
Class<T> resolved = (Class<T>) type.resolve();
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
package org.springframework.boot.context.properties.bind;
|
package org.springframework.boot.context.properties.bind;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -307,6 +309,29 @@ class ValueObjectBinderTests {
|
||||||
.withStackTraceContaining("Parameter of type int must have a non-empty default value.");
|
.withStackTraceContaining("Parameter of type int must have a non-empty default value.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bindWhenBindingToPathTypeWithValue() { // gh-21263
|
||||||
|
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||||
|
source.put("test.name", "test");
|
||||||
|
source.put("test.path", "specific_value");
|
||||||
|
this.sources.add(source);
|
||||||
|
Bindable<PathBean> target = Bindable.of(PathBean.class);
|
||||||
|
PathBean bound = this.binder.bind("test", target).get();
|
||||||
|
assertThat(bound.getName()).isEqualTo("test");
|
||||||
|
assertThat(bound.getPath()).isEqualTo(Paths.get("specific_value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void bindWhenBindingToPathTypeWithDefaultValue() { // gh-21263
|
||||||
|
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||||
|
source.put("test.name", "test");
|
||||||
|
this.sources.add(source);
|
||||||
|
Bindable<PathBean> target = Bindable.of(PathBean.class);
|
||||||
|
PathBean bound = this.binder.bindOrCreate("test", target);
|
||||||
|
assertThat(bound.getName()).isEqualTo("test");
|
||||||
|
assertThat(bound.getPath()).isEqualTo(Paths.get("default_value"));
|
||||||
|
}
|
||||||
|
|
||||||
private void noConfigurationProperty(BindException ex) {
|
private void noConfigurationProperty(BindException ex) {
|
||||||
assertThat(ex.getProperty()).isNull();
|
assertThat(ex.getProperty()).isNull();
|
||||||
}
|
}
|
||||||
|
@ -684,4 +709,25 @@ class ValueObjectBinderTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class PathBean {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final Path path;
|
||||||
|
|
||||||
|
PathBean(String name, @DefaultValue("default_value") Path path) {
|
||||||
|
this.name = name;
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path getPath() {
|
||||||
|
return this.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue