适用于所有Enums的Spring自定义转换器 [英] Spring custom converter for all Enums

查看:149
本文介绍了适用于所有Enums的Spring自定义转换器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 int getID() MyEnum withID(int)构建了许多枚举类为了持久性目的,我将一个ID专用于枚举值(从而避免因枚举的外部存储而导致的订单/名称更改)。

I've built many Enum classes with int getID() and MyEnum withID(int) methods that allow me to dedicate an ID to the enum values for persistence purposes (thus avoiding changes due to order/name change with regards to external storage of the enum).

我是喜欢构建一个自定义转换器来做一些反射来查找这些方法,并在找不到它们时使用它们或备份到Ordinal / String转换。

I'd like to build a custom converter that does some reflection to look for these methods, and use them or back up to Ordinal/String conversions when they are not found.

是否通用枚举转换器似乎对任何人都有可能?这只是我对转换器的第二次尝试。

Does a generic Enum converter seem possible to anyone? This is only my second foray into Converters.

推荐答案

我会说你正试图解决错误的问题。我通常坚持将字符串作为字符串,从而避免这个问题。缺点当然是更大的数据库字段,但这并不重要。

I'd say you are trying to solve the wrong problem. I usually persist enums as Strings and thereby avoid this problem in the first place. The drawback is of course a larger DB field, but that's hardly significant.

那说:

我会说这一般是可能的,但不是一个干净的方式。我要做的是让所有这些枚举实现一个公共接口(只是一个标记接口或一个包含 int getId()方法的接口)。现在只为这个界面注册你的PropertyEditor,然后你就不会破坏太多的标准功能。

I'd say it's possible in general, but not in a clean way. What I'd do is let all these enums implement a common interface (either just a marker interface or one that contains the int getId() method). Now register your PropertyEditor for this interface only, then you're not breaking too much standard functionality.

然后,你的下一个问题是你依赖于静态工厂方法,这不能以通用的方式完成。当然你的PropertyEditor可以这样做:

Then, your next problem is that you are relying on static factory methods, which can not be done in a generic way. Of course your PropertyEditor can do:

enumClass.getDeclaredMethod("withId", int.class).invoke(id)

但我称之为非常hacky。这样的事情:

but I'd call that very hacky. How about something like this:

Object target = null;
for(Object e : EnumSet.allOf(yourEnumClass)){
    if(e instanceof MyInterface && ((MyInterface)e).getId()==thisId){
        target = e;
        break;
    }
}
return target;

现在你没有使用任何静态工厂方法,只要你的枚举你有编译时安全性实现一个通用接口。

Now you are not using any static factory methods and you have compile time safety, as long as your enums implement a common interface.

更新:使用新的Converter SPI变得更容易。使用自定义ConverterFactory

Update: with the new Converter SPI it gets easier. Use a custom ConverterFactory:

public class CustomEnumConverterFactory implements
    ConverterFactory<String, Enum<?>>{

    @Override
    public <T extends Enum<?>> Converter<String, T> getConverter(
        final Class<T> targetType){
        return WithId.class.isAssignableFrom(targetType)
            ? new EnumWithIdConverter(targetType)
            : new StandardEnumConverter(targetType);
    }

}

像这样注册:

<bean id="conversionService"
    class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
        <!-- converters is a set of both converters and converterfactories -->
        <bean class="foo.bar.CustomEnumConverterFactory" />
    </property>
</bean>

这篇关于适用于所有Enums的Spring自定义转换器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆