Skip to content

Commit 0709c76

Browse files
committed
Merge branch '2.2.x' into 2.3.x
Closes gh-23614
2 parents 61181b4 + ce70e7d commit 0709c76

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.springframework.core.convert.ConversionService;
3131
import org.springframework.core.convert.converter.Converter;
3232
import org.springframework.core.convert.converter.GenericConverter;
33+
import org.springframework.format.Formatter;
3334

3435
/**
3536
* Utility to deduce the {@link ConversionService} to use for configuration properties
@@ -62,9 +63,13 @@ private static class Factory {
6263

6364
private final List<GenericConverter> genericConverters;
6465

66+
@SuppressWarnings("rawtypes")
67+
private final List<Formatter> formatters;
68+
6569
Factory(BeanFactory beanFactory) {
6670
this.converters = beans(beanFactory, Converter.class, ConfigurationPropertiesBinding.VALUE);
6771
this.genericConverters = beans(beanFactory, GenericConverter.class, ConfigurationPropertiesBinding.VALUE);
72+
this.formatters = beans(beanFactory, Formatter.class, ConfigurationPropertiesBinding.VALUE);
6873
}
6974

7075
private <T> List<T> beans(BeanFactory beanFactory, Class<T> type, String qualifier) {
@@ -80,7 +85,7 @@ private <T> List<T> beans(Class<T> type, String qualifier, ListableBeanFactory b
8085
}
8186

8287
ConversionService create() {
83-
if (this.converters.isEmpty() && this.genericConverters.isEmpty()) {
88+
if (this.converters.isEmpty() && this.genericConverters.isEmpty() && this.formatters.isEmpty()) {
8489
return ApplicationConversionService.getSharedInstance();
8590
}
8691
ApplicationConversionService conversionService = new ApplicationConversionService();
@@ -90,6 +95,9 @@ ConversionService create() {
9095
for (GenericConverter genericConverter : this.genericConverters) {
9196
conversionService.addConverter(genericConverter);
9297
}
98+
for (Formatter<?> formatter : this.formatters) {
99+
conversionService.addFormatter(formatter);
100+
}
93101
return conversionService;
94102
}
95103

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

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818

1919
import java.beans.PropertyEditorSupport;
2020
import java.io.File;
21+
import java.text.ParseException;
2122
import java.time.Duration;
2223
import java.util.ArrayList;
2324
import java.util.Collections;
2425
import java.util.HashMap;
2526
import java.util.LinkedHashMap;
2627
import java.util.List;
28+
import java.util.Locale;
2729
import java.util.Map;
2830
import java.util.Properties;
2931
import java.util.Set;
@@ -73,6 +75,7 @@
7375
import org.springframework.core.io.ProtocolResolver;
7476
import org.springframework.core.io.Resource;
7577
import org.springframework.core.io.ResourceLoader;
78+
import org.springframework.format.Formatter;
7679
import org.springframework.mock.env.MockEnvironment;
7780
import org.springframework.stereotype.Component;
7881
import org.springframework.test.context.support.TestPropertySourceUtils;
@@ -609,7 +612,7 @@ void customProtocolResolver() {
609612
}
610613

611614
@Test
612-
void loadShouldUseConfigurationConverter() {
615+
void loadShouldUseConverterBean() {
613616
prepareConverterContext(ConverterConfiguration.class, PersonProperties.class);
614617
Person person = this.context.getBean(PersonProperties.class).getPerson();
615618
assertThat(person.firstName).isEqualTo("John");
@@ -625,13 +628,21 @@ void loadWhenConfigurationConverterIsNotQualifiedShouldNotConvert() {
625628
}
626629

627630
@Test
628-
void loadShouldUseGenericConfigurationConverter() {
631+
void loadShouldUseGenericConverterBean() {
629632
prepareConverterContext(GenericConverterConfiguration.class, PersonProperties.class);
630633
Person person = this.context.getBean(PersonProperties.class).getPerson();
631634
assertThat(person.firstName).isEqualTo("John");
632635
assertThat(person.lastName).isEqualTo("Smith");
633636
}
634637

638+
@Test
639+
void loadShouldUseFormatterBean() {
640+
prepareConverterContext(FormatterConfiguration.class, PersonProperties.class);
641+
Person person = this.context.getBean(PersonProperties.class).getPerson();
642+
assertThat(person.firstName).isEqualTo("John");
643+
assertThat(person.lastName).isEqualTo("Smith");
644+
}
645+
635646
@Test
636647
void loadWhenGenericConfigurationConverterIsNotQualifiedShouldNotConvert() {
637648
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(
@@ -1246,6 +1257,17 @@ GenericConverter genericPersonConverter() {
12461257

12471258
}
12481259

1260+
@Configuration(proxyBeanMethods = false)
1261+
static class FormatterConfiguration {
1262+
1263+
@Bean
1264+
@ConfigurationPropertiesBinding
1265+
Formatter<Person> personFormatter() {
1266+
return new PersonFormatter();
1267+
}
1268+
1269+
}
1270+
12491271
@Configuration(proxyBeanMethods = false)
12501272
static class NonQualifiedGenericConverterConfiguration {
12511273

@@ -2011,12 +2033,27 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
20112033

20122034
}
20132035

2036+
static class PersonFormatter implements Formatter<Person> {
2037+
2038+
@Override
2039+
public String print(Person person, Locale locale) {
2040+
return person.getFirstName() + " " + person.getLastName();
2041+
}
2042+
2043+
@Override
2044+
public Person parse(String text, Locale locale) throws ParseException {
2045+
String[] content = text.split(" ");
2046+
return new Person(content[0], content[1]);
2047+
}
2048+
2049+
}
2050+
20142051
static class PersonPropertyEditor extends PropertyEditorSupport {
20152052

20162053
@Override
20172054
public void setAsText(String text) throws IllegalArgumentException {
2018-
String[] split = text.split(",");
2019-
setValue(new Person(split[1], split[0]));
2055+
String[] content = text.split(",");
2056+
setValue(new Person(content[1], content[0]));
20202057
}
20212058

20222059
}
@@ -2032,6 +2069,14 @@ static class Person {
20322069
this.lastName = lastName;
20332070
}
20342071

2072+
String getFirstName() {
2073+
return this.firstName;
2074+
}
2075+
2076+
String getLastName() {
2077+
return this.lastName;
2078+
}
2079+
20352080
}
20362081

20372082
static class Foo {

0 commit comments

Comments
 (0)