Merge branch '2.1.x'

Closes gh-16857
pull/16875/head
Phillip Webb 6 years ago
commit e03f3b8e9a

@ -102,16 +102,16 @@ class JavaBeanBinder implements BeanBinder {
private static Bean<?> cached; private static Bean<?> cached;
private final Class<?> type; private final ResolvableType type;
private final ResolvableType resolvableType; private final Class<?> resolvedType;
private final Map<String, BeanProperty> properties = new LinkedHashMap<>(); private final Map<String, BeanProperty> properties = new LinkedHashMap<>();
Bean(ResolvableType resolvableType, Class<?> type) { Bean(ResolvableType type, Class<?> resolvedType) {
this.resolvableType = resolvableType;
this.type = type; this.type = type;
putProperties(type); this.resolvedType = resolvedType;
putProperties(resolvedType);
} }
private void putProperties(Class<?> type) { private void putProperties(Class<?> type) {
@ -155,7 +155,7 @@ class JavaBeanBinder implements BeanBinder {
} }
private BeanProperty getBeanProperty(String name) { private BeanProperty getBeanProperty(String name) {
return new BeanProperty(name, this.resolvableType); return new BeanProperty(name, this.type);
} }
private void addField(Field field) { private void addField(Field field) {
@ -165,10 +165,6 @@ class JavaBeanBinder implements BeanBinder {
} }
} }
public Class<?> getType() {
return this.type;
}
public Map<String, BeanProperty> getProperties() { public Map<String, BeanProperty> getProperties() {
return this.properties; return this.properties;
} }
@ -181,27 +177,36 @@ class JavaBeanBinder implements BeanBinder {
instance = target.getValue().get(); instance = target.getValue().get();
} }
if (instance == null) { if (instance == null) {
instance = (T) BeanUtils.instantiateClass(this.type); instance = (T) BeanUtils.instantiateClass(this.resolvedType);
} }
return instance; return instance;
}); });
} }
private boolean isOfDifferentType(ResolvableType targetType) {
if (this.type.hasGenerics() || targetType.hasGenerics()) {
return !this.type.equals(targetType);
}
return this.resolvedType == null
|| !this.resolvedType.equals(targetType.resolve());
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> Bean<T> get(Bindable<T> bindable, boolean canCallGetValue) { public static <T> Bean<T> get(Bindable<T> bindable, boolean canCallGetValue) {
Class<?> type = bindable.getType().resolve(Object.class); ResolvableType type = bindable.getType();
Class<?> resolvedType = type.resolve(Object.class);
Supplier<T> value = bindable.getValue(); Supplier<T> value = bindable.getValue();
T instance = null; T instance = null;
if (canCallGetValue && value != null) { if (canCallGetValue && value != null) {
instance = value.get(); instance = value.get();
type = (instance != null) ? instance.getClass() : type; resolvedType = (instance != null) ? instance.getClass() : resolvedType;
} }
if (instance == null && !isInstantiable(type)) { if (instance == null && !isInstantiable(resolvedType)) {
return null; return null;
} }
Bean<?> bean = Bean.cached; Bean<?> bean = Bean.cached;
if (bean == null || !type.equals(bean.getType())) { if (bean == null || bean.isOfDifferentType(type)) {
bean = new Bean<>(bindable.getType(), type); bean = new Bean<>(type, resolvedType);
cached = bean; cached = bean;
} }
return (Bean<T>) bean; return (Bean<T>) bean;

@ -494,6 +494,19 @@ public class JavaBeanBinderTests {
assertThat(bean.getCounter()).isEqualTo(42); assertThat(bean.getCounter()).isEqualTo(42);
} }
@Test
public void bindToClassShouldCacheWithGenerics() {
// gh-16821
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("foo.integers[a].value", "1");
source.put("foo.booleans[b].value", "true");
this.sources.add(source);
ExampleWithGenericMap bean = this.binder
.bind("foo", Bindable.of(ExampleWithGenericMap.class)).get();
assertThat(bean.getIntegers().get("a").getValue()).isEqualTo(1);
assertThat(bean.getBooleans().get("b").getValue()).isEqualTo(true);
}
public static class ExampleValueBean { public static class ExampleValueBean {
private int intValue; private int intValue;
@ -914,4 +927,34 @@ public class JavaBeanBinderTests {
} }
public static class ExampleWithGenericMap {
private final Map<String, GenericValue<Integer>> integers = new LinkedHashMap<>();
private final Map<String, GenericValue<Boolean>> booleans = new LinkedHashMap<>();
public Map<String, GenericValue<Integer>> getIntegers() {
return this.integers;
}
public Map<String, GenericValue<Boolean>> getBooleans() {
return this.booleans;
}
}
public static class GenericValue<T> {
private T value;
public T getValue() {
return this.value;
}
public void setValue(T value) {
this.value = value;
}
}
} }

Loading…
Cancel
Save