From 2bc3d8d01f2d6630c5d48a3a182de195301be024 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 17 Sep 2018 12:59:47 -0700 Subject: [PATCH] Use shared BindConverter when possible Update the `Binder` so that a single shares static `BindConverter` is used whenever possible. Closes gh-14562 --- .../properties/bind/BindConverter.java | 21 ++++++++++++++++-- .../boot/context/properties/bind/Binder.java | 2 +- .../properties/bind/BindConverterTests.java | 22 +++++++++---------- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindConverter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindConverter.java index daf60ba523..c5b60e7584 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindConverter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindConverter.java @@ -47,7 +47,7 @@ import org.springframework.util.Assert; * @author Phillip Webb * @author Andy Wilkinson */ -class BindConverter { +final class BindConverter { private static final Set> EXCLUDED_EDITORS; static { @@ -56,9 +56,11 @@ class BindConverter { EXCLUDED_EDITORS = Collections.unmodifiableSet(excluded); } + private static BindConverter sharedInstance; + private final ConversionService conversionService; - BindConverter(ConversionService conversionService, + private BindConverter(ConversionService conversionService, Consumer propertyEditorInitializer) { Assert.notNull(conversionService, "ConversionService must not be null"); List conversionServices = getConversionServices( @@ -97,6 +99,21 @@ class BindConverter { new ResolvableTypeDescriptor(type, annotations)); } + public static BindConverter get(ConversionService conversionService, + Consumer 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}. */ diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java index 65009bf5f1..8b102b2fc9 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/Binder.java @@ -392,7 +392,7 @@ public class Binder { private ConfigurationProperty configurationProperty; Context() { - this.converter = new BindConverter(Binder.this.conversionService, + this.converter = BindConverter.get(Binder.this.conversionService, Binder.this.propertyEditorInitializer); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java index bed2ccc515..07cf1889b5 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindConverterTests.java @@ -65,17 +65,17 @@ public class BindConverterTests { public void createWhenConversionServiceIsNullShouldThrowException() { this.thrown.expect(IllegalArgumentException.class); this.thrown.expectMessage("ConversionService must not be null"); - new BindConverter(null, null); + BindConverter.get(null, null); } @Test public void createWhenPropertyEditorInitializerIsNullShouldCreate() { - new BindConverter(ApplicationConversionService.getSharedInstance(), null); + BindConverter.get(ApplicationConversionService.getSharedInstance(), null); } @Test public void createWhenPropertyEditorInitializerIsNotNullShouldUseToInitialize() { - new BindConverter(ApplicationConversionService.getSharedInstance(), + BindConverter.get(ApplicationConversionService.getSharedInstance(), this.propertyEditorInitializer); verify(this.propertyEditorInitializer).accept(any(PropertyEditorRegistry.class)); } @@ -128,8 +128,8 @@ public class BindConverterTests { @Test public void canConvertWhenNotPropertyEditorAndConversionServiceCannotConvertShouldReturnFalse() { - BindConverter bindConverter = new BindConverter( - ApplicationConversionService.getSharedInstance(), null); + BindConverter bindConverter = BindConverter + .get(ApplicationConversionService.getSharedInstance(), null); assertThat(bindConverter.canConvert("test", ResolvableType.forClass(SampleType.class))).isFalse(); } @@ -189,8 +189,8 @@ public class BindConverterTests { @Test public void convertWhenNotPropertyEditorAndConversionServiceCannotConvertShouldThrowException() { - BindConverter bindConverter = new BindConverter( - ApplicationConversionService.getSharedInstance(), null); + BindConverter bindConverter = BindConverter + .get(ApplicationConversionService.getSharedInstance(), null); this.thrown.expect(ConverterNotFoundException.class); bindConverter.convert("test", ResolvableType.forClass(SampleType.class)); } @@ -199,7 +199,7 @@ public class BindConverterTests { public void convertWhenConvertingToFileShouldExcludeFileEditor() { // For back compatibility we want true file conversion and not an accidental // classpath resource reference. See gh-12163 - BindConverter bindConverter = new BindConverter(new GenericConversionService(), + BindConverter bindConverter = BindConverter.get(new GenericConversionService(), null); File result = bindConverter.convert(".", ResolvableType.forClass(File.class)); assertThat(result.getPath()).isEqualTo("."); @@ -207,7 +207,7 @@ public class BindConverterTests { @Test public void fallsBackToApplicationConversionService() { - BindConverter bindConverter = new BindConverter(new GenericConversionService(), + BindConverter bindConverter = BindConverter.get(new GenericConversionService(), null); Duration result = bindConverter.convert("10s", ResolvableType.forClass(Duration.class)); @@ -216,14 +216,14 @@ public class BindConverterTests { private BindConverter getPropertyEditorOnlyBindConverter( Consumer propertyEditorInitializer) { - return new BindConverter(new ThrowingConversionService(), + return BindConverter.get(new ThrowingConversionService(), propertyEditorInitializer); } private BindConverter getBindConverter(Converter converter) { GenericConversionService conversionService = new GenericConversionService(); conversionService.addConverter(converter); - return new BindConverter(conversionService, null); + return BindConverter.get(conversionService, null); } private void registerSampleTypeEditor(PropertyEditorRegistry registry) {