3

我有很多枚举实现了一个名为 Codeable 的接口。我想在从 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);
    }

}

}

这是弹簧配置

<!-- 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,为什么会这样?我怎样才能让我的优先于另一个?

4

1 回答 1

2

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

我的解决方法是:

  1. 取消注册默认的字符串到枚举转换器 -registry.removeConvertible(String.class, Enum.class)其中 registry 是 FormatterRegistry 的一个实例
  2. 编写一个字符串到 mycustomenum 的转换器
  3. 编写一个包罗万象的字符串到枚举转换器,它进行类型检查 ( MyEnumType.class.isAssignableFrom(targetType)) 并根据结果委托给我的自定义转换器或默认的字符串到枚举转换器

请注意,这种方法有几个问题,其中:StringToEnumConverter是一个包私有类,所以我不得不将它复制粘贴到我自己的代码库中。此外,这不是解决此问题的理想方法;它不是很“有弹性”。

很想听到这个的替代答案。

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

主要更新

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

在 Spring 的文档中,我发现:

GenericConversionService 是一种通用实现,旨在以编程方式或以声明方式显式配置为 Spring bean。DefaultConversionService 是一个子类,为了方便,它在 core.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);
}

现在一切正常,感觉明显不那么老套了。

于 2014-02-05T22:30:26.313 回答