5.5 Spring 3 Type Conversion

Spring 3 introduces a core.convert package that provides a general type conversion system. The system defines a SPI to implement type conversion logic, as well as a API to execute type conversions at runtime. Within a Spring container, if configured, this system can be used as an alternative to PropertyEditors to convert externalized bean property value strings to required property types. The public API may also be used anywhere in your application where type conversion is needed.

5.5.1 Converter SPI

The SPI to implement type conversion logic is simple and strongly typed:

package org.springframework.core.converter;
    
public interface Converter<S, T> {

    T convert(S source) throws Exception;    
        
}
			

To create your own Converter, simply implement the interface above. Parameterize S as the type you are converting from, and T as the type you are converting to. For each call to convert(S), the source argument is guaranteed to be NOT null. Your Converter may throw any Exception if conversion fails. An IllegalArgumentException is often thrown to report an invalid source value. Take care to ensure your Converter implementation is thread safe.

Several converter implementations are provided in the core.convert.converters package as a convenience. These include converters to from String to Numbers and other common types. Note StringToInteger as an example Converter implementation:

package org.springframework.core.convert.converters;
    
public class StringToInteger implements Converter<String, Integer> {

    public Integer convert(String source) {
        return Integer.valueOf(source);
    }
    
}
			

5.5.2 ConverterFactory

When you need to centralize the conversion logic for an entire class hierarchy, for example, when converting from String to java.lang.Enum objects, implement a ConverterFactory:

package org.springframework.core.converter;
    
public interface ConverterFactory<S, R> {

    <T extends R> Converter<S, T> getConverter(Class<T> targetType);  
          
}
			

Parameterize S to be type you are converting from, and R to be base type defining the range of classes you can convert to. Then implement getConverter(Class<T>), where T is a subclass of R.

Note the StringToEnum ConverterFactory as an example:

public class StringToEnumFactory implements ConverterFactory<String, Enum> {

    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnum(targetType);
    }

    private final class StringToEnum<T extends Enum> implements Converter<String, T> {

        private Class<T> enumType;
		
        public StringToEnum(Class<T> enumType) {
            this.enumType = enumType;
        }
        
        public T convert(String source) throws Exception {
            return (T) Enum.valueOf(this.enumType, source.trim());
        }
    }
}
			

5.5.3 ConversionService API

The ConversionService defines a public API for executing type conversion logic at runtime. Converters are always executed behind this API. User code should not depend on the Converter SPI.

public interface ConversionService {

    boolean canConvert(Class<?> sourceType, Class<?> targetType);
    
    <T> T convert(Object source, Class<T> targetType);
	
}
			

Most ConversionService implementations also implement ConverterRegistry, which provides a SPI for registering converters. Internally, a ConversionService implementation delegates to its registered Converters and ConverterFactories to carry out type conversion logic.

Two ConversionService implementations are provided with the system in the core.convert.support package. GenericConversionService is a generic implementation designed to be explicitly configured, either programatically or declaratively as a Spring bean. DefaultConversionService is a subclass that pre-registers the common Converters in the core.converter package as a convenience.

5.5.4 Configuring a ConversionService

A ConversionService is a stateless object designed to be instantiated at application startup, then shared between multiple threads. In a Spring application, you typically configure a ConversionService instance per Spring container (or ApplicationContext). That ConversionService will be picked up by Spring and then used whenever a type conversion needs to be performed by the framework. You may also inject this ConversionService into any of your beans and invoke it directly. If no ConversionService is registered with Spring, the original PropertyEditor-based system is used.

To register the DefaultConversionService with Spring, simply configure it as a bean with the id conversionService:

<bean id="conversionService" class="org.springframework.core.convert.support.DefaultConversionService" />
			

To override the default converter set with your own custom converter(s), set the converters property:

<bean id="conversionService" class="org.springframework.core.convert.support.DefaultConversionService">
    <property name="converters">
        <list>
            <bean class="example.MyCustomConverter" />
        </list>
    </property>
</bean>
			

5.5.5 Using a ConversionService programatically

To work with a ConversionService instance programatically, simply inject a reference to it like you would any other bean:

@Service
public class MyService {

    @Autowired
    public MyService(ConversionService conversionService) {
        this.conversionService = conversionService;
    }
    
    public void doIt() {
        this.conversionService.convert(...)
    }
}