diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java index 128936a60b6..75277ced803 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java @@ -165,7 +165,8 @@ class JavaBeanBinder implements DataObjectBinder { private boolean isCandidate(Method method) { int modifiers = method.getModifiers(); return !Modifier.isPrivate(modifiers) && !Modifier.isProtected(modifiers) && !Modifier.isAbstract(modifiers) - && !Modifier.isStatic(modifiers) && !Object.class.equals(method.getDeclaringClass()) + && !Modifier.isStatic(modifiers) && !method.isBridge() + && !Object.class.equals(method.getDeclaringClass()) && !Class.class.equals(method.getDeclaringClass()) && method.getName().indexOf('$') == -1; } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java index c40a606d0dd..c7482bd9418 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java @@ -318,6 +318,18 @@ class JavaBeanBinderTests { assertThat(bean.getValueBean()).isNull(); } + @Test + void bindToClassWithOverriddenPropertyShouldSetSubclassProperty() { + MockConfigurationPropertySource source = new MockConfigurationPropertySource(); + source.put("foo.value-bean.int-value", "123"); + source.put("foo.value-bean.sub-int-value", "456"); + this.sources.add(source); + ExampleNestedSubclassBean bean = this.binder.bind("foo", Bindable.of(ExampleNestedSubclassBean.class)).get(); + assertThat(bean.getValueBean()).isNotNull(); + assertThat(bean.getValueBean().getIntValue()).isEqualTo(123); + assertThat(bean.getValueBean().getSubIntValue()).isEqualTo(456); + } + @Test void bindToClassWhenPropertiesMissingShouldReturnUnbound() { MockConfigurationPropertySource source = new MockConfigurationPropertySource(); @@ -804,6 +816,35 @@ class JavaBeanBinderTests { } + static class ExampleNestedSubclassBean extends ExampleNestedBean { + + private ExampleValueSubclassBean valueBean; + + @Override + ExampleValueSubclassBean getValueBean() { + return this.valueBean; + } + + void setValueBean(ExampleValueSubclassBean valueBean) { + this.valueBean = valueBean; + } + + static class ExampleValueSubclassBean extends ExampleValueBean { + + private int subIntValue; + + int getSubIntValue() { + return this.subIntValue; + } + + void setSubIntValue(int intValue) { + this.subIntValue = intValue; + } + + } + + } + static class ExampleWithNonDefaultConstructor { private String value;