Skip to content

Commit ce70e7d

Browse files
committed
Merge branch '2.1.x' into 2.2.x
Closes gh-23613
2 parents c523295 + 1db2f5f commit ce70e7d

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;
@@ -72,6 +74,7 @@
7274
import org.springframework.core.io.ProtocolResolver;
7375
import org.springframework.core.io.Resource;
7476
import org.springframework.core.io.ResourceLoader;
77+
import org.springframework.format.Formatter;
7578
import org.springframework.mock.env.MockEnvironment;
7679
import org.springframework.stereotype.Component;
7780
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(
@@ -1238,6 +1249,17 @@ GenericConverter genericPersonConverter() {
12381249

12391250
}
12401251

1252+
@Configuration(proxyBeanMethods = false)
1253+
static class FormatterConfiguration {
1254+
1255+
@Bean
1256+
@ConfigurationPropertiesBinding
1257+
Formatter<Person> personFormatter() {
1258+
return new PersonFormatter();
1259+
}
1260+
1261+
}
1262+
12411263
@Configuration(proxyBeanMethods = false)
12421264
static class NonQualifiedGenericConverterConfiguration {
12431265

@@ -2003,12 +2025,27 @@ public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor t
20032025

20042026
}
20052027

2028+
static class PersonFormatter implements Formatter<Person> {
2029+
2030+
@Override
2031+
public String print(Person person, Locale locale) {
2032+
return person.getFirstName() + " " + person.getLastName();
2033+
}
2034+
2035+
@Override
2036+
public Person parse(String text, Locale locale) throws ParseException {
2037+
String[] content = text.split(" ");
2038+
return new Person(content[0], content[1]);
2039+
}
2040+
2041+
}
2042+
20062043
static class PersonPropertyEditor extends PropertyEditorSupport {
20072044

20082045
@Override
20092046
public void setAsText(String text) throws IllegalArgumentException {
2010-
String[] split = text.split(",");
2011-
setValue(new Person(split[1], split[0]));
2047+
String[] content = text.split(",");
2048+
setValue(new Person(content[1], content[0]));
20122049
}
20132050

20142051
}
@@ -2024,6 +2061,14 @@ static class Person {
20242061
this.lastName = lastName;
20252062
}
20262063

2064+
String getFirstName() {
2065+
return this.firstName;
2066+
}
2067+
2068+
String getLastName() {
2069+
return this.lastName;
2070+
}
2071+
20272072
}
20282073

20292074
static class Foo {

0 commit comments

Comments
 (0)