From 692b1ef636ec9b5525c5f800288a483b8760fdc8 Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Fri, 20 Nov 2009 14:43:12 +0000 Subject: [PATCH] found hotspot; added ConverisonServiceFactoryBean --- .../DefaultListableBeanFactoryTests.java | 2 +- .../support/ConversionServiceFactoryBean.java | 97 +++++++++++++++++++ .../support/FormattingConversionService.java | 2 +- ...ormattingConversionServiceFactoryBean.java | 34 ++++--- .../support/ConversionServiceFactory.java | 14 +-- .../support/DefaultConversionTests.java | 38 ++++---- .../spel/support/StandardTypeConverter.java | 12 ++- ...essionTestsUsingCoreConversionService.java | 2 +- 8 files changed, 149 insertions(+), 52 deletions(-) create mode 100644 org.springframework.context/src/main/java/org/springframework/context/support/ConversionServiceFactoryBean.java diff --git a/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java b/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java index 8569ebb2432..41f193f3ecb 100644 --- a/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java +++ b/org.springframework.beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java @@ -841,7 +841,7 @@ public final class DefaultListableBeanFactoryTests { @Test public void testCustomConverter() { DefaultListableBeanFactory lbf = new DefaultListableBeanFactory(); - GenericConversionService conversionService = (GenericConversionService) ConversionServiceFactory.createDefault(); + GenericConversionService conversionService = (GenericConversionService) ConversionServiceFactory.createDefaultConversionService(); conversionService.addConverter(new Converter() { public Float convert(String source) { try { diff --git a/org.springframework.context/src/main/java/org/springframework/context/support/ConversionServiceFactoryBean.java b/org.springframework.context/src/main/java/org/springframework/context/support/ConversionServiceFactoryBean.java new file mode 100644 index 00000000000..ce70c1c54a3 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/context/support/ConversionServiceFactoryBean.java @@ -0,0 +1,97 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.context.support; + +import java.util.Set; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.converter.Converter; +import org.springframework.core.convert.converter.ConverterFactory; +import org.springframework.core.convert.converter.ConverterRegistry; +import org.springframework.core.convert.converter.GenericConverter; +import org.springframework.core.convert.support.ConversionServiceFactory; + +/** + * A factory for a ConversionService that installs default converters appropriate for most environments. + * Set the converters property to supplement or override the default converters. + * @author Keith Donald + * @since 3.0 + * @see ConversionServiceFactory#createDefaultConversionService() + */ +public class ConversionServiceFactoryBean implements FactoryBean, InitializingBean { + + private Set converters; + + private ConversionService conversionService; + + /** + * Configure the set of custom Converters that should be added. + */ + public void setConverters(Set converters) { + this.converters = converters; + } + + // implementing InitializingBean + + public void afterPropertiesSet() { + this.conversionService = createConversionService(); + registerConverters(this.converters, (ConverterRegistry) this.conversionService); + } + + // implementing FactoryBean + + public ConversionService getObject() { + return this.conversionService; + } + + public Class getObjectType() { + return ConversionService.class; + } + + public boolean isSingleton() { + return true; + } + + // subclassing hooks + + /** + * Creates the ConversionService instance returned by this factory bean. + */ + protected ConversionService createConversionService() { + return ConversionServiceFactory.createDefaultConversionService(); + } + + // internal helpers + + private void registerConverters(Set converters, ConverterRegistry registry) { + if (converters != null) { + for (Object converter : converters) { + if (converter instanceof Converter) { + registry.addConverter((Converter) converter); + } else if (converter instanceof ConverterFactory) { + registry.addConverterFactory((ConverterFactory) converter); + } else if (converter instanceof GenericConverter) { + registry.addGenericConverter((GenericConverter) converter); + } else { + throw new IllegalArgumentException("Each converter must implement one of the Converter, ConverterFactory, or GenericConverter interfaces"); + } + } + } + } + +} diff --git a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java index a043972767a..de89a0c77a7 100644 --- a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java +++ b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionService.java @@ -41,7 +41,7 @@ import org.springframework.format.Printer; */ public class FormattingConversionService implements FormatterRegistry, ConversionService { - private ConversionService conversionService = ConversionServiceFactory.createDefault(); + private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService(); // implementing FormattingRegistry diff --git a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionServiceFactoryBean.java b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionServiceFactoryBean.java index 8473f219f75..860a6a9fb5a 100644 --- a/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionServiceFactoryBean.java +++ b/org.springframework.context/src/main/java/org/springframework/format/support/FormattingConversionServiceFactoryBean.java @@ -18,6 +18,7 @@ package org.springframework.format.support; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.convert.ConversionService; +import org.springframework.format.FormatterRegistry; import org.springframework.format.datetime.joda.JodaTimeFormattingConfigurer; import org.springframework.format.number.NumberFormatAnnotationFormatterFactory; import org.springframework.format.number.NumberFormatter; @@ -25,18 +26,22 @@ import org.springframework.util.ClassUtils; /** * A factory for a FormattingConversionService that installs default formatters for common types such as numbers and datetimes. + * Subclasses may override {@link #installFormatters(FormatterRegistry)} to register custom formatters. * @author Keith Donald * @since 3.0 */ public class FormattingConversionServiceFactoryBean implements FactoryBean, InitializingBean { - private FormattingConversionService conversionService = new FormattingConversionService(); - + private static final boolean jodaTimePresent = ClassUtils.isPresent( + "org.joda.time.DateTime", FormattingConversionService.class.getClassLoader()); + + private FormattingConversionService conversionService; + // implementing InitializingBean public void afterPropertiesSet() { - installNumberFormatting(); - installJodaTimeFormattingIfPresent(); + this.conversionService = new FormattingConversionService(); + installFormatters(this.conversionService); } // implementing FactoryBean @@ -45,7 +50,7 @@ public class FormattingConversionServiceFactoryBean implements FactoryBean getObjectType() { + public Class getObjectType() { return ConversionService.class; } @@ -53,17 +58,14 @@ public class FormattingConversionServiceFactoryBean implements FactoryBean stringList = new ArrayList(); - stringList.add("foo"); - stringList.add("bar"); - - List frozenList = Collections.unmodifiableList(stringList); - - List converted = conversionService.convert(frozenList, List.class); - - // The converted list should contain all the elements in the original list - Assert.assertEquals(frozenList, converted); - // Looks like it was supposed to be a copy (but CollectionToCollectionConverter - // doesn't work that way right now). Commented out (DS). - // Assert.assertNotSame(frozenList, converted); - } + private ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService(); @Test public void testStringToCharacter() { @@ -740,4 +722,22 @@ public class DefaultConversionTests { } } + @Test + @SuppressWarnings("unchecked") + public void testUnmodifiableListConversion() { + List stringList = new ArrayList(); + stringList.add("foo"); + stringList.add("bar"); + + List frozenList = Collections.unmodifiableList(stringList); + + List converted = conversionService.convert(frozenList, List.class); + + // The converted list should contain all the elements in the original list + Assert.assertEquals(frozenList, converted); + // TODO Looks like it was supposed to be a copy (but CollectionToCollectionConverter + // doesn't work that way right now). Commented out (DS). + // Assert.assertNotSame(frozenList, converted); + } + } diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java index dfa431cde16..939068fca79 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/StandardTypeConverter.java @@ -37,10 +37,12 @@ import org.springframework.util.Assert; */ public class StandardTypeConverter implements TypeConverter { + private static ConversionService DEFAULT_INSTANCE; + private final ConversionService conversionService; public StandardTypeConverter() { - this.conversionService = ConversionServiceFactory.getDefault(); + this.conversionService = getDefaultConversionService(); } public StandardTypeConverter(ConversionService conversionService) { @@ -64,4 +66,12 @@ public class StandardTypeConverter implements TypeConverter { } } + private ConversionService getDefaultConversionService() { + synchronized(this) { + if (DEFAULT_INSTANCE == null) { + DEFAULT_INSTANCE = ConversionServiceFactory.createDefaultConversionService(); + } + } + return DEFAULT_INSTANCE; + } } diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java index e8d220b44dc..973ac5d1454 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/ExpressionTestsUsingCoreConversionService.java @@ -99,7 +99,7 @@ public class ExpressionTestsUsingCoreConversionService extends ExpressionTestCas */ private static class TypeConvertorUsingConversionService implements TypeConverter { - private final ConversionService service = ConversionServiceFactory.createDefault(); + private final ConversionService service = ConversionServiceFactory.createDefaultConversionService(); public boolean canConvert(Class sourceType, Class targetType) { return this.service.canConvert(sourceType, targetType);