Merge branch 'gh-10702'
This commit is contained in:
commit
5fb9162875
|
|
@ -31,8 +31,15 @@ abstract class AggregateBinder<T> {
|
|||
|
||||
private final BindContext context;
|
||||
|
||||
AggregateBinder(BindContext context) {
|
||||
private final boolean allowRecursiveBinding;
|
||||
|
||||
AggregateBinder(BindContext context, boolean allowRecursiveBinding) {
|
||||
this.context = context;
|
||||
this.allowRecursiveBinding = allowRecursiveBinding;
|
||||
}
|
||||
|
||||
boolean isAllowRecursiveBinding() {
|
||||
return this.allowRecursiveBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -188,13 +188,14 @@ public class Binder {
|
|||
}
|
||||
|
||||
protected final <T> T bind(ConfigurationPropertyName name, Bindable<T> target,
|
||||
BindHandler handler, Context context, boolean skipIfHasBoundBean) {
|
||||
BindHandler handler, Context context, boolean allowRecursiveBinding) {
|
||||
context.clearConfigurationProperty();
|
||||
try {
|
||||
if (!handler.onStart(name, target, context)) {
|
||||
return null;
|
||||
}
|
||||
Object bound = bindObject(name, target, handler, context, skipIfHasBoundBean);
|
||||
Object bound = bindObject(name, target, handler, context,
|
||||
allowRecursiveBinding);
|
||||
return handleBindResult(name, target, handler, context, bound);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
|
@ -232,7 +233,7 @@ public class Binder {
|
|||
}
|
||||
|
||||
private <T> Object bindObject(ConfigurationPropertyName name, Bindable<T> target,
|
||||
BindHandler handler, Context context, boolean skipIfHasBoundBean)
|
||||
BindHandler handler, Context context, boolean allowRecursiveBinding)
|
||||
throws Exception {
|
||||
ConfigurationProperty property = findProperty(name, context);
|
||||
if (property == null && containsNoDescendantOf(context.streamSources(), name)) {
|
||||
|
|
@ -245,7 +246,7 @@ public class Binder {
|
|||
if (property != null) {
|
||||
return bindProperty(name, target, handler, context, property);
|
||||
}
|
||||
return bindBean(name, target, handler, context, skipIfHasBoundBean);
|
||||
return bindBean(name, target, handler, context, allowRecursiveBinding);
|
||||
}
|
||||
|
||||
private AggregateBinder<?> getAggregateBinder(Bindable<?> target, Context context) {
|
||||
|
|
@ -266,7 +267,7 @@ public class Binder {
|
|||
BindHandler handler, Context context, AggregateBinder<?> aggregateBinder) {
|
||||
AggregateElementBinder elementBinder = (itemName, itemTarget, source) -> {
|
||||
Supplier<?> supplier = () -> bind(itemName, itemTarget, handler, context,
|
||||
false);
|
||||
aggregateBinder.isAllowRecursiveBinding());
|
||||
return context.withSource(source, supplier);
|
||||
};
|
||||
return context.withIncreasedDepth(
|
||||
|
|
@ -290,15 +291,15 @@ public class Binder {
|
|||
}
|
||||
|
||||
private Object bindBean(ConfigurationPropertyName name, Bindable<?> target,
|
||||
BindHandler handler, Context context, boolean skipIfHasBoundBean) {
|
||||
BindHandler handler, Context context, boolean allowRecursiveBinding) {
|
||||
if (containsNoDescendantOf(context.streamSources(), name)
|
||||
|| isUnbindableBean(name, target, context)) {
|
||||
return null;
|
||||
}
|
||||
BeanPropertyBinder propertyBinder = (propertyName, propertyTarget) -> bind(
|
||||
name.append(propertyName), propertyTarget, handler, context, true);
|
||||
name.append(propertyName), propertyTarget, handler, context, false);
|
||||
Class<?> type = target.getType().resolve();
|
||||
if (skipIfHasBoundBean && context.hasBoundBean(type)) {
|
||||
if (!allowRecursiveBinding && context.hasBoundBean(type)) {
|
||||
return null;
|
||||
}
|
||||
return context.withBean(type, () -> {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ abstract class IndexedElementsBinder<T> extends AggregateBinder<T> {
|
|||
private static final String INDEX_ZERO = "[0]";
|
||||
|
||||
IndexedElementsBinder(BindContext context) {
|
||||
super(context);
|
||||
super(context, false);
|
||||
}
|
||||
|
||||
protected final void bindIndexed(ConfigurationPropertyName name, Bindable<?> target,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class MapBinder extends AggregateBinder<Map<Object, Object>> {
|
|||
.mapOf(String.class, String.class);
|
||||
|
||||
MapBinder(BindContext context) {
|
||||
super(context);
|
||||
super(context, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -351,6 +351,32 @@ public class CollectionBinderTests {
|
|||
assertThat(result.getItemsSet()).containsExactly("a", "b", "c");
|
||||
}
|
||||
|
||||
public void bindToBeanWithNestedCollectionShouldPopulateCollection()
|
||||
throws Exception {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("foo.value", "one");
|
||||
source.put("foo.foos[0].value", "two");
|
||||
source.put("foo.foos[1].value", "three");
|
||||
this.sources.add(source);
|
||||
Bindable<BeanWithNestedCollection> target = Bindable
|
||||
.of(BeanWithNestedCollection.class);
|
||||
BeanWithNestedCollection foo = this.binder.bind("foo", target).get();
|
||||
assertThat(foo.getValue()).isNotNull();
|
||||
assertThat(foo.getFoos().get(0).getValue()).isEqualTo("two");
|
||||
assertThat(foo.getFoos().get(1).getValue()).isEqualTo("three");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindToBeanWithNestedCollectionAndNonIterableSourceShouldNotFail()
|
||||
throws Exception {
|
||||
// gh-10702
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
this.sources.add(source.nonIterable());
|
||||
Bindable<BeanWithNestedCollection> target = Bindable
|
||||
.of(BeanWithNestedCollection.class);
|
||||
this.binder.bind("foo", target);
|
||||
}
|
||||
|
||||
public static class ExampleCollectionBean {
|
||||
|
||||
private List<String> items = new ArrayList<>();
|
||||
|
|
@ -401,4 +427,27 @@ public class CollectionBinderTests {
|
|||
|
||||
}
|
||||
|
||||
public static class BeanWithNestedCollection {
|
||||
|
||||
private String value;
|
||||
|
||||
private List<BeanWithNestedCollection> foos;
|
||||
|
||||
public List<BeanWithNestedCollection> getFoos() {
|
||||
return this.foos;
|
||||
}
|
||||
|
||||
public void setFoos(List<BeanWithNestedCollection> foos) {
|
||||
this.foos = foos;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue