Skip to content

Commit 8b740c0

Browse files
committed
Merge branch '2.3.x' into master
Closes gh-23615
2 parents 745e22e + 0709c76 commit 8b740c0

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,6 +18,7 @@
1818

1919
import java.beans.PropertyEditorSupport;
2020
import java.io.File;
21+
import java.text.ParseException;
2122
import java.time.Duration;
2223
import java.time.Period;
2324
import java.time.temporal.ChronoUnit;
@@ -26,6 +27,7 @@
2627
import java.util.HashMap;
2728
import java.util.LinkedHashMap;
2829
import java.util.List;
30+
import java.util.Locale;
2931
import java.util.Map;
3032
import java.util.Properties;
3133
import java.util.Set;
@@ -81,6 +83,7 @@
8183
import org.springframework.core.io.ProtocolResolver;
8284
import org.springframework.core.io.Resource;
8385
import org.springframework.core.io.ResourceLoader;
86+
import org.springframework.format.Formatter;
8487
import org.springframework.mock.env.MockEnvironment;
8588
import org.springframework.stereotype.Component;
8689
import org.springframework.test.context.support.TestPropertySourceUtils;
@@ -618,7 +621,7 @@ void customProtocolResolver() {
618621
}
619622

620623
@Test
621-
void loadShouldUseConfigurationConverter() {
624+
void loadShouldUseConverterBean() {
622625
prepareConverterContext(ConverterConfiguration.class, PersonProperties.class);
623626
Person person = this.context.getBean(PersonProperties.class).getPerson();
624627
assertThat(person.firstName).isEqualTo("John");
@@ -634,13 +637,21 @@ void loadWhenConfigurationConverterIsNotQualifiedShouldNotConvert() {
634637
}
635638

636639
@Test
637-
void loadShouldUseGenericConfigurationConverter() {
640+
void loadShouldUseGenericConverterBean() {
638641
prepareConverterContext(GenericConverterConfiguration.class, PersonProperties.class);
639642
Person person = this.context.getBean(PersonProperties.class).getPerson();
640643
assertThat(person.firstName).isEqualTo("John");
641644
assertThat(person.lastName).isEqualTo("Smith");
642645
}
643646

647+
@Test
648+
void loadShouldUseFormatterBean() {
649+
prepareConverterContext(FormatterConfiguration.class, PersonProperties.class);
650+
Person person = this.context.getBean(PersonProperties.class).getPerson();
651+
assertThat(person.firstName).isEqualTo("John");
652+
assertThat(person.lastName).isEqualTo("Smith");
653+
}
654+
644655
@Test
645656
void loadWhenGenericConfigurationConverterIsNotQualifiedShouldNotConvert() {
646657
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(
@@ -1326,6 +1337,17 @@ GenericConverter genericPersonConverter() {
13261337

13271338
}
13281339

1340+
@Configuration(proxyBeanMethods = false)
1341+
static class FormatterConfiguration {
1342+
1343+
@Bean
1344+
@ConfigurationPropertiesBinding
1345+
Formatter<Person> personFormatter() {
1346+
return new PersonFormatter();
1347+
}
1348+
1349+
}
1350+
13291351
@Configuration(proxyBeanMethods = false)
13301352
static class NonQualifiedGenericConverterConfiguration {
13311353

@@ -2158,12 +2180,27 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
21582180

21592181
}
21602182

2183+
static class PersonFormatter implements Formatter<Person> {
2184+
2185+
@Override
2186+
public String print(Person person, Locale locale) {
2187+
return person.getFirstName() + " " + person.getLastName();
2188+
}
2189+
2190+
@Override
2191+
public Person parse(String text, Locale locale) throws ParseException {
2192+
String[] content = text.split(" ");
2193+
return new Person(content[0], content[1]);
2194+
}
2195+
2196+
}
2197+
21612198
static class PersonPropertyEditor extends PropertyEditorSupport {
21622199

21632200
@Override
21642201
public void setAsText(String text) throws IllegalArgumentException {
2165-
String[] split = text.split(",");
2166-
setValue(new Person(split[1], split[0]));
2202+
String[] content = text.split(",");
2203+
setValue(new Person(content[1], content[0]));
21672204
}
21682205

21692206
}
@@ -2179,6 +2216,14 @@ static class Person {
21792216
this.lastName = lastName;
21802217
}
21812218

2219+
String getFirstName() {
2220+
return this.firstName;
2221+
}
2222+
2223+
String getLastName() {
2224+
return this.lastName;
2225+
}
2226+
21822227
}
21832228

21842229
static class Foo {

0 commit comments

Comments
 (0)