Allow binding when 'is' method also exists

Improve the `JavaBeanBinder` so that an bean that has both a `get` and
`is` method can still be bound.

Closes gh-23007
This commit is contained in:
Phillip Webb 2020-09-21 16:34:02 -07:00
parent fde2e440bb
commit c885a15aea
2 changed files with 60 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -140,9 +140,11 @@ class JavaBeanBinder implements DataObjectBinder {
}
}
for (Method method : declaredMethods) {
addMethodIfPossible(method, "get", 0, BeanProperty::addGetter);
addMethodIfPossible(method, "is", 0, BeanProperty::addGetter);
}
for (Method method : declaredMethods) {
addMethodIfPossible(method, "get", 0, BeanProperty::addGetter);
}
for (Method method : declaredMethods) {
addMethodIfPossible(method, "set", 1, BeanProperty::addSetter);
}
@ -280,11 +282,15 @@ class JavaBeanBinder implements DataObjectBinder {
}
void addGetter(Method getter) {
if (this.getter == null) {
if (this.getter == null || isBetterGetter(getter)) {
this.getter = getter;
}
}
private boolean isBetterGetter(Method getter) {
return this.getter != null && this.getter.getName().startsWith("is");
}
void addSetter(Method setter) {
if (this.setter == null || isBetterSetter(setter)) {
this.setter = setter;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -540,6 +540,24 @@ class JavaBeanBinderTests {
assertThat(bean.getProperty()).isEqualTo("test");
}
@Test // gh-23007
void bindWhenBeanWithGetSetIsMethodsFoundUsesGetterThatMatchesSetter() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("test.names", "spring,boot");
this.sources.add(source);
JavaBeanWithGetSetIs bean = this.binder.bind("test", Bindable.of(JavaBeanWithGetSetIs.class)).get();
assertThat(bean.getNames()).containsExactly("spring", "boot");
}
@Test // gh-23007
void bindWhenBeanWithGetIsMethodsFoundDoesNotUseIsGetter() {
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
source.put("test.names", "spring,boot");
this.sources.add(source);
JavaBeanWithGetIs bean = this.binder.bind("test", Bindable.of(JavaBeanWithGetIs.class)).get();
assertThat(bean.getNames()).containsExactly("spring", "boot");
}
static class ExampleValueBean {
private int intValue;
@ -1036,4 +1054,36 @@ class JavaBeanBinderTests {
}
static class JavaBeanWithGetSetIs {
private List<String> names = new ArrayList<>();
List<String> getNames() {
return this.names;
}
void setNames(List<String> names) {
this.names = names;
}
boolean isNames() {
return !this.names.isEmpty();
}
}
static class JavaBeanWithGetIs {
private List<String> names = new ArrayList<>();
boolean isNames() {
return !this.names.isEmpty();
}
List<String> getNames() {
return this.names;
}
}
}