Skip to content

Commit 46acb6f

Browse files
committed
Ignore bridge methods when binding java beans
Update `JavaBeanBinder` so that bridge methods are ignored when binding. Fixes gh-33105
1 parent e03c2e8 commit 46acb6f

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
import java.util.Arrays;
2525
import java.util.Comparator;
2626
import java.util.LinkedHashMap;
27+
import java.util.LinkedHashSet;
2728
import java.util.Map;
29+
import java.util.Set;
2830
import java.util.function.BiConsumer;
2931
import java.util.function.Function;
3032
import java.util.function.Supplier;
@@ -34,6 +36,7 @@
3436
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
3537
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
3638
import org.springframework.boot.context.properties.source.ConfigurationPropertyState;
39+
import org.springframework.core.BridgeMethodResolver;
3740
import org.springframework.core.MethodParameter;
3841
import org.springframework.core.ResolvableType;
3942

@@ -129,13 +132,22 @@ static class Bean<T> {
129132

130133
private void addProperties(Class<?> type) {
131134
while (type != null && !Object.class.equals(type)) {
132-
Method[] declaredMethods = getSorted(type, Class::getDeclaredMethods, Method::getName);
135+
Method[] declaredMethods = getSorted(type, this::getDeclaredMethods, Method::getName);
133136
Field[] declaredFields = getSorted(type, Class::getDeclaredFields, Field::getName);
134137
addProperties(declaredMethods, declaredFields);
135138
type = type.getSuperclass();
136139
}
137140
}
138141

142+
private Method[] getDeclaredMethods(Class<?> type) {
143+
Method[] methods = type.getDeclaredMethods();
144+
Set<Method> result = new LinkedHashSet<>(methods.length);
145+
for (Method method : methods) {
146+
result.add(BridgeMethodResolver.findBridgedMethod(method));
147+
}
148+
return result.toArray(new Method[0]);
149+
}
150+
139151
private <S, E> E[] getSorted(S source, Function<S, E[]> elements, Function<E, String> name) {
140152
E[] result = elements.apply(source);
141153
Arrays.sort(result, Comparator.comparing(name));

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
3636
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
3737
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
3838
import org.springframework.boot.context.properties.source.MockConfigurationPropertySource;
39+
import org.springframework.boot.convert.ApplicationConversionService;
3940
import org.springframework.boot.convert.Delimiter;
4041
import org.springframework.core.ResolvableType;
4142
import org.springframework.core.convert.ConversionService;
@@ -585,6 +586,18 @@ void bindWhenBeanWithGetIsMethodsFoundDoesNotUseIsGetter() {
585586
assertThat(bean.getNames()).containsExactly("spring", "boot");
586587
}
587588

589+
@Test // gh-33105
590+
void bindWhenHasBridgeMethods() {
591+
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
592+
source.put("test.value", "spring-boot");
593+
this.sources.add(source);
594+
ApplicationConversionService conversionService = new ApplicationConversionService();
595+
conversionService.addConverter(String.class, BridgeType.class, BridgeType::new);
596+
Binder binder = new Binder(this.sources, null, conversionService);
597+
BridgeMethods bean = binder.bind("test", Bindable.of(BridgeMethods.class)).get();
598+
assertThat(bean.getValue()).hasToString("spring-boot");
599+
}
600+
588601
static class ExampleValueBean {
589602

590603
private int intValue;
@@ -1178,4 +1191,46 @@ void setGamma(int gamma) {
11781191

11791192
}
11801193

1194+
static class BridgeMethodsBase<T extends BridgeBaseType> {
1195+
1196+
private T value;
1197+
1198+
T getValue() {
1199+
return this.value;
1200+
}
1201+
1202+
void setValue(T value) {
1203+
this.value = value;
1204+
}
1205+
1206+
}
1207+
1208+
static class BridgeMethods extends BridgeMethodsBase<BridgeType> {
1209+
1210+
@Override
1211+
BridgeType getValue() {
1212+
return super.getValue();
1213+
}
1214+
1215+
}
1216+
1217+
static class BridgeBaseType {
1218+
1219+
}
1220+
1221+
static class BridgeType extends BridgeBaseType {
1222+
1223+
private String value;
1224+
1225+
BridgeType(String value) {
1226+
this.value = value;
1227+
}
1228+
1229+
@Override
1230+
public String toString() {
1231+
return this.value;
1232+
}
1233+
1234+
}
1235+
11811236
}

0 commit comments

Comments
 (0)