Spring类型转换没有生效

时间:2013-07-16 01:12:38

标签: spring-mvc type-conversion

我有很多实现名为Codeable的接口的Enums。我想从json反序列化并尝试使用ConverterFactory

时进行反向查找
public class StringToCodeableConverterFactory implements ConverterFactory<String, Codeable> {

@Override
public <T extends Codeable> Converter<String, T> getConverter(
        Class<T> targetType) {
    return new StringToCodeableConverter<T>(targetType);
}

private final class StringToCodeableConverter<T extends Codeable> implements Converter<String, T> {

    private Class<T> enumType;

    public StringToCodeableConverter(Class<T> enumType) {
        this.enumType = enumType;
    }

    @Override
    public T convert(String source) {
        return CodeableUtil.get(this.enumType, source);
    }

}

}

这是spring config

<!-- Custom Converters from String to Java Type-->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
    <property name="converters">
        <list>
            <bean class="com.duetto.model.StringToCodeableConverterFactory" />
        </list>    
    </property>
</bean>

<mvc:annotation-driven conversion-service="conversionService">

经过一番挖掘,我发现Spring正在使用默认的StringToEnumConverterFactory而不是我的StringToCodeableConverterFactory,为什么会这样?如何让我优先于另一个呢?

1 个答案:

答案 0 :(得分:2)

我注意到的是DefaultConversionService的默认值包括StringToEnumConversion,它首先出现在服务的可能转换器列表中。因此,我从未被击中,每次都在尝试标准的Enum转换。

我的解决方法是:

  1. 取消注册默认的字符串到枚举转换器 - registry.removeConvertible(String.class, Enum.class)其中registry是FormatterRegistry的实例
  2. 写一个字符串到mycustomenum转换器
  3. 编写一个包含类型检查(MyEnumType.class.isAssignableFrom(targetType))的无所不包的字符串到枚举转换器,并根据结果委托给我的自定义转换器或默认的字符串到枚举转换器
  4. 注意这种方法有几个问题,其中包括:StringToEnumConverter是一个包私有类,所以我不得不将它复制粘贴到我自己的代码库中。另外,这不是解决这个问题的理想方法;它不是很“有弹性”。

    很想听到替代答案。

    值得注意的是,我正在使用Spring 3.2.6

    重大更新

    我找到了一种更清洁的方式,请注意我使用的是注释配置而不是xml,但是主体应该是相同的。

    在Spring的文档中,我发现:

      

    GenericConversionService是一个旨在实现的通用实现   显式配置,以编程方式或声明方式配置为   春豆。 DefaultConversionService是一个预注册的子类   核心.converter包中的常见转换器为方便起见。

    所以,我现在已经覆盖了如下配置:

    @Override
    public FormattingConversionService mvcConversionService() {
        // use FormattingConversionService here rather than GenericFormattingConversionService (the default) 
        // because it does not automatically register defaults
        FormattingConversionService conversionService = new FormattingConversionService();
        addFormatters(conversionService);
        return conversionService;
    }
    
    @Override
    protected void addFormatters(FormatterRegistry registry) {
        // register custom enum handler first
        registry.addConverterFactory(new MyCustomEnumConverterFactory());
        // now add in spring's defaults
        DefaultConversionService.addDefaultConverters(registry);
        DefaultFormattingConversionService.addDefaultFormatters(registry);
    }
    

    现在一切正常,感觉不那么骇人听闻。