Commit 2bc3d8d0 authored by Phillip Webb's avatar Phillip Webb

Use shared BindConverter when possible

Update the `Binder` so that a single shares static `BindConverter` is
used whenever possible.

Closes gh-14562
parent 865b7ae4
...@@ -47,7 +47,7 @@ import org.springframework.util.Assert; ...@@ -47,7 +47,7 @@ import org.springframework.util.Assert;
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class BindConverter { final class BindConverter {
private static final Set<Class<?>> EXCLUDED_EDITORS; private static final Set<Class<?>> EXCLUDED_EDITORS;
static { static {
...@@ -56,9 +56,11 @@ class BindConverter { ...@@ -56,9 +56,11 @@ class BindConverter {
EXCLUDED_EDITORS = Collections.unmodifiableSet(excluded); EXCLUDED_EDITORS = Collections.unmodifiableSet(excluded);
} }
private static BindConverter sharedInstance;
private final ConversionService conversionService; private final ConversionService conversionService;
BindConverter(ConversionService conversionService, private BindConverter(ConversionService conversionService,
Consumer<PropertyEditorRegistry> propertyEditorInitializer) { Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
Assert.notNull(conversionService, "ConversionService must not be null"); Assert.notNull(conversionService, "ConversionService must not be null");
List<ConversionService> conversionServices = getConversionServices( List<ConversionService> conversionServices = getConversionServices(
...@@ -97,6 +99,21 @@ class BindConverter { ...@@ -97,6 +99,21 @@ class BindConverter {
new ResolvableTypeDescriptor(type, annotations)); new ResolvableTypeDescriptor(type, annotations));
} }
public static BindConverter get(ConversionService conversionService,
Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
if (conversionService == ApplicationConversionService.getSharedInstance()
&& propertyEditorInitializer == null) {
BindConverter instance = sharedInstance;
if (instance == null) {
instance = new BindConverter(conversionService,
propertyEditorInitializer);
sharedInstance = instance;
}
return instance;
}
return new BindConverter(conversionService, propertyEditorInitializer);
}
/** /**
* A {@link TypeDescriptor} backed by a {@link ResolvableType}. * A {@link TypeDescriptor} backed by a {@link ResolvableType}.
*/ */
......
...@@ -392,7 +392,7 @@ public class Binder { ...@@ -392,7 +392,7 @@ public class Binder {
private ConfigurationProperty configurationProperty; private ConfigurationProperty configurationProperty;
Context() { Context() {
this.converter = new BindConverter(Binder.this.conversionService, this.converter = BindConverter.get(Binder.this.conversionService,
Binder.this.propertyEditorInitializer); Binder.this.propertyEditorInitializer);
} }
......
...@@ -65,17 +65,17 @@ public class BindConverterTests { ...@@ -65,17 +65,17 @@ public class BindConverterTests {
public void createWhenConversionServiceIsNullShouldThrowException() { public void createWhenConversionServiceIsNullShouldThrowException() {
this.thrown.expect(IllegalArgumentException.class); this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("ConversionService must not be null"); this.thrown.expectMessage("ConversionService must not be null");
new BindConverter(null, null); BindConverter.get(null, null);
} }
@Test @Test
public void createWhenPropertyEditorInitializerIsNullShouldCreate() { public void createWhenPropertyEditorInitializerIsNullShouldCreate() {
new BindConverter(ApplicationConversionService.getSharedInstance(), null); BindConverter.get(ApplicationConversionService.getSharedInstance(), null);
} }
@Test @Test
public void createWhenPropertyEditorInitializerIsNotNullShouldUseToInitialize() { public void createWhenPropertyEditorInitializerIsNotNullShouldUseToInitialize() {
new BindConverter(ApplicationConversionService.getSharedInstance(), BindConverter.get(ApplicationConversionService.getSharedInstance(),
this.propertyEditorInitializer); this.propertyEditorInitializer);
verify(this.propertyEditorInitializer).accept(any(PropertyEditorRegistry.class)); verify(this.propertyEditorInitializer).accept(any(PropertyEditorRegistry.class));
} }
...@@ -128,8 +128,8 @@ public class BindConverterTests { ...@@ -128,8 +128,8 @@ public class BindConverterTests {
@Test @Test
public void canConvertWhenNotPropertyEditorAndConversionServiceCannotConvertShouldReturnFalse() { public void canConvertWhenNotPropertyEditorAndConversionServiceCannotConvertShouldReturnFalse() {
BindConverter bindConverter = new BindConverter( BindConverter bindConverter = BindConverter
ApplicationConversionService.getSharedInstance(), null); .get(ApplicationConversionService.getSharedInstance(), null);
assertThat(bindConverter.canConvert("test", assertThat(bindConverter.canConvert("test",
ResolvableType.forClass(SampleType.class))).isFalse(); ResolvableType.forClass(SampleType.class))).isFalse();
} }
...@@ -189,8 +189,8 @@ public class BindConverterTests { ...@@ -189,8 +189,8 @@ public class BindConverterTests {
@Test @Test
public void convertWhenNotPropertyEditorAndConversionServiceCannotConvertShouldThrowException() { public void convertWhenNotPropertyEditorAndConversionServiceCannotConvertShouldThrowException() {
BindConverter bindConverter = new BindConverter( BindConverter bindConverter = BindConverter
ApplicationConversionService.getSharedInstance(), null); .get(ApplicationConversionService.getSharedInstance(), null);
this.thrown.expect(ConverterNotFoundException.class); this.thrown.expect(ConverterNotFoundException.class);
bindConverter.convert("test", ResolvableType.forClass(SampleType.class)); bindConverter.convert("test", ResolvableType.forClass(SampleType.class));
} }
...@@ -199,7 +199,7 @@ public class BindConverterTests { ...@@ -199,7 +199,7 @@ public class BindConverterTests {
public void convertWhenConvertingToFileShouldExcludeFileEditor() { public void convertWhenConvertingToFileShouldExcludeFileEditor() {
// For back compatibility we want true file conversion and not an accidental // For back compatibility we want true file conversion and not an accidental
// classpath resource reference. See gh-12163 // classpath resource reference. See gh-12163
BindConverter bindConverter = new BindConverter(new GenericConversionService(), BindConverter bindConverter = BindConverter.get(new GenericConversionService(),
null); null);
File result = bindConverter.convert(".", ResolvableType.forClass(File.class)); File result = bindConverter.convert(".", ResolvableType.forClass(File.class));
assertThat(result.getPath()).isEqualTo("."); assertThat(result.getPath()).isEqualTo(".");
...@@ -207,7 +207,7 @@ public class BindConverterTests { ...@@ -207,7 +207,7 @@ public class BindConverterTests {
@Test @Test
public void fallsBackToApplicationConversionService() { public void fallsBackToApplicationConversionService() {
BindConverter bindConverter = new BindConverter(new GenericConversionService(), BindConverter bindConverter = BindConverter.get(new GenericConversionService(),
null); null);
Duration result = bindConverter.convert("10s", Duration result = bindConverter.convert("10s",
ResolvableType.forClass(Duration.class)); ResolvableType.forClass(Duration.class));
...@@ -216,14 +216,14 @@ public class BindConverterTests { ...@@ -216,14 +216,14 @@ public class BindConverterTests {
private BindConverter getPropertyEditorOnlyBindConverter( private BindConverter getPropertyEditorOnlyBindConverter(
Consumer<PropertyEditorRegistry> propertyEditorInitializer) { Consumer<PropertyEditorRegistry> propertyEditorInitializer) {
return new BindConverter(new ThrowingConversionService(), return BindConverter.get(new ThrowingConversionService(),
propertyEditorInitializer); propertyEditorInitializer);
} }
private BindConverter getBindConverter(Converter<?, ?> converter) { private BindConverter getBindConverter(Converter<?, ?> converter) {
GenericConversionService conversionService = new GenericConversionService(); GenericConversionService conversionService = new GenericConversionService();
conversionService.addConverter(converter); conversionService.addConverter(converter);
return new BindConverter(conversionService, null); return BindConverter.get(conversionService, null);
} }
private void registerSampleTypeEditor(PropertyEditorRegistry registry) { private void registerSampleTypeEditor(PropertyEditorRegistry registry) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment