diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java index 7ddee6aaa26..7455a13fedf 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/CollectionBinder.java @@ -40,12 +40,11 @@ class CollectionBinder extends IndexedElementsBinder> { @Override protected Object bindAggregate(ConfigurationPropertyName name, Bindable target, AggregateElementBinder elementBinder) { - Class collectionType = (target.getValue() != null) ? List.class : target.getType().resolve(Object.class); ResolvableType aggregateType = ResolvableType.forClassWithGenerics(List.class, target.getType().asCollection().getGenerics()); ResolvableType elementType = target.getType().asCollection().getGeneric(); IndexedCollectionSupplier result = new IndexedCollectionSupplier( - () -> CollectionFactory.createCollection(collectionType, elementType.resolve(), 0)); + () -> CollectionFactory.createCollection(List.class, elementType.resolve(), 0)); bindIndexed(name, target, elementBinder, aggregateType, elementType, result); if (result.wasSupplied()) { return result.get(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java index 98f78b06bec..241c9fab078 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java @@ -1161,6 +1161,19 @@ class ConfigurationPropertiesTests { assertThat(properties.getProp()).isEqualTo("alpha"); } + @Test + void loadWhenBindingToConstructorParametersWithConversionToCustomListImplementation() { + load(ConstructorBoundCustomListPropertiesConfiguration.class, "test.values=a,b"); + assertThat(this.context.getBean(ConstructorBoundCustomListProperties.class).getValues()).containsExactly("a", + "b"); + } + + @Test + void loadWhenBindingToJavaBeanWithConversionToCustomListImplementation() { + load(SetterBoundCustomListPropertiesConfiguration.class, "test.values=a,b"); + assertThat(this.context.getBean(SetterBoundCustomListProperties.class).getValues()).containsExactly("a", "b"); + } + private AnnotationConfigApplicationContext load(Class configuration, String... inlinedProperties) { return load(new Class[] { configuration }, inlinedProperties); } @@ -3043,4 +3056,80 @@ class ConfigurationPropertiesTests { } + @EnableConfigurationProperties(ConstructorBoundCustomListProperties.class) + static class ConstructorBoundCustomListPropertiesConfiguration { + + @Bean + @ConfigurationPropertiesBinding + static Converter, CustomList> arrayListToCustomList() { + return new Converter, CustomList>() { + + @Override + public CustomList convert(ArrayList source) { + return new CustomList<>(source); + } + + }; + + } + + } + + @ConfigurationProperties("test") + static class ConstructorBoundCustomListProperties { + + private final CustomList values; + + ConstructorBoundCustomListProperties(CustomList values) { + this.values = values; + } + + CustomList getValues() { + return this.values; + } + + } + + @EnableConfigurationProperties(SetterBoundCustomListProperties.class) + static class SetterBoundCustomListPropertiesConfiguration { + + @Bean + @ConfigurationPropertiesBinding + static Converter, CustomList> arrayListToCustomList() { + return new Converter, CustomList>() { + + @Override + public CustomList convert(ArrayList source) { + return new CustomList<>(source); + } + + }; + + } + + } + + @ConfigurationProperties("test") + static class SetterBoundCustomListProperties { + + private CustomList values; + + CustomList getValues() { + return this.values; + } + + void setValues(CustomList values) { + this.values = values; + } + + } + + static final class CustomList extends ArrayList { + + CustomList(List delegate) { + super(delegate); + } + + } + }