|
|
@ -1,5 +1,5 @@
|
|
|
|
/*
|
|
|
|
/*
|
|
|
|
* Copyright 2012-2020 the original author or authors.
|
|
|
|
* Copyright 2012-2022 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.
|
|
|
@ -17,6 +17,7 @@
|
|
|
|
package org.springframework.boot.context.properties.bind;
|
|
|
|
package org.springframework.boot.context.properties.bind;
|
|
|
|
|
|
|
|
|
|
|
|
import java.lang.annotation.Annotation;
|
|
|
|
import java.lang.annotation.Annotation;
|
|
|
|
|
|
|
|
import java.lang.reflect.Array;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
|
|
import java.lang.reflect.Constructor;
|
|
|
|
import java.lang.reflect.Modifier;
|
|
|
|
import java.lang.reflect.Modifier;
|
|
|
|
import java.lang.reflect.Parameter;
|
|
|
|
import java.lang.reflect.Parameter;
|
|
|
@ -25,6 +26,7 @@ import java.util.Collection;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.Optional;
|
|
|
|
|
|
|
|
|
|
|
|
import kotlin.reflect.KFunction;
|
|
|
|
import kotlin.reflect.KFunction;
|
|
|
|
import kotlin.reflect.KParameter;
|
|
|
|
import kotlin.reflect.KParameter;
|
|
|
@ -32,6 +34,7 @@ import kotlin.reflect.jvm.ReflectJvmMapping;
|
|
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
|
import org.springframework.beans.BeanUtils;
|
|
|
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
|
|
|
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
|
|
|
|
|
|
|
|
import org.springframework.core.CollectionFactory;
|
|
|
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
|
|
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
|
|
|
import org.springframework.core.KotlinDetector;
|
|
|
|
import org.springframework.core.KotlinDetector;
|
|
|
|
import org.springframework.core.MethodParameter;
|
|
|
|
import org.springframework.core.MethodParameter;
|
|
|
@ -101,7 +104,7 @@ class ValueObjectBinder implements DataObjectBinder {
|
|
|
|
if (annotation instanceof DefaultValue) {
|
|
|
|
if (annotation instanceof DefaultValue) {
|
|
|
|
String[] defaultValue = ((DefaultValue) annotation).value();
|
|
|
|
String[] defaultValue = ((DefaultValue) annotation).value();
|
|
|
|
if (defaultValue.length == 0) {
|
|
|
|
if (defaultValue.length == 0) {
|
|
|
|
return getNewInstanceIfPossible(context, type);
|
|
|
|
return getNewDefaultValueInstanceIfPossible(context, type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return convertDefaultValue(context.getConverter(), defaultValue, type, annotations);
|
|
|
|
return convertDefaultValue(context.getConverter(), defaultValue, type, annotations);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -124,7 +127,7 @@ class ValueObjectBinder implements DataObjectBinder {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
private <T> T getNewInstanceIfPossible(Binder.Context context, ResolvableType type) {
|
|
|
|
private <T> T getNewDefaultValueInstanceIfPossible(Binder.Context context, ResolvableType type) {
|
|
|
|
Class<T> resolved = (Class<T>) type.resolve();
|
|
|
|
Class<T> resolved = (Class<T>) type.resolve();
|
|
|
|
Assert.state(resolved == null || isEmptyDefaultValueAllowed(resolved),
|
|
|
|
Assert.state(resolved == null || isEmptyDefaultValueAllowed(resolved),
|
|
|
|
() -> "Parameter of type " + type + " must have a non-empty default value.");
|
|
|
|
() -> "Parameter of type " + type + " must have a non-empty default value.");
|
|
|
@ -132,14 +135,27 @@ class ValueObjectBinder implements DataObjectBinder {
|
|
|
|
if (instance != null) {
|
|
|
|
if (instance != null) {
|
|
|
|
return instance;
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (resolved != null) ? BeanUtils.instantiateClass(resolved) : null;
|
|
|
|
if (resolved != null) {
|
|
|
|
|
|
|
|
if (Optional.class == resolved) {
|
|
|
|
|
|
|
|
return (T) Optional.empty();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Collection.class.isAssignableFrom(resolved)) {
|
|
|
|
|
|
|
|
return (T) CollectionFactory.createCollection(resolved, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Map.class.isAssignableFrom(resolved)) {
|
|
|
|
|
|
|
|
return (T) CollectionFactory.createMap(resolved, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resolved.isArray()) {
|
|
|
|
|
|
|
|
return (T) Array.newInstance(resolved.getComponentType(), 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return BeanUtils.instantiateClass(resolved);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isEmptyDefaultValueAllowed(Class<?> type) {
|
|
|
|
private boolean isEmptyDefaultValueAllowed(Class<?> type) {
|
|
|
|
if (type.isPrimitive() || type.isEnum() || isAggregate(type) || type.getName().startsWith("java.lang")) {
|
|
|
|
return (Optional.class == type || isAggregate(type))
|
|
|
|
return false;
|
|
|
|
|| !(type.isPrimitive() || type.isEnum() || type.getName().startsWith("java.lang"));
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private boolean isAggregate(Class<?> type) {
|
|
|
|
private boolean isAggregate(Class<?> type) {
|
|
|
|