适用于所有枚举的弹簧定制转换器
我已经构建了许多Enum类和方法,这些方法允许我将ID专用于枚举值以进行持久性(从而避免由于枚举的外部存储方面的顺序/名称更改而导致的更改)。int getID()
MyEnum withID(int)
我想构建一个自定义转换器,该转换器会进行一些反射以查找这些方法,并在找不到它们时使用它们或备份到Ordinal/String转换。
通用枚举转换器对任何人来说似乎都是可能的吗?这只是我第二次涉足转换器。
我已经构建了许多Enum类和方法,这些方法允许我将ID专用于枚举值以进行持久性(从而避免由于枚举的外部存储方面的顺序/名称更改而导致的更改)。int getID()
MyEnum withID(int)
我想构建一个自定义转换器,该转换器会进行一些反射以查找这些方法,并在找不到它们时使用它们或备份到Ordinal/String转换。
通用枚举转换器对任何人来说似乎都是可能的吗?这只是我第二次涉足转换器。
我会说你试图解决错误的问题。我通常将枚举保留为字符串,从而首先避免了这个问题。缺点当然是数据库字段更大,但这并不重要。
可是:
我会说这在一般情况下是可能的,但不是以一种干净的方式。我要做的是让所有这些枚举实现一个通用接口(或者只是一个标记接口或包含该方法的接口)。现在,仅为此接口注册您的属性编辑器,这样您就不会破坏太多的标准功能。int getId()
然后,您的下一个问题是您依赖于静态工厂方法,这无法以通用方式完成。当然,您的属性编辑器可以执行以下操作:
enumClass.getDeclaredMethod("withId", int.class).invoke(id)
但我会说这很笨拙。像这样的东西怎么样:
Object target = null;
for(Object e : EnumSet.allOf(yourEnumClass)){
if(e instanceof MyInterface && ((MyInterface)e).getId()==thisId){
target = e;
break;
}
}
return target;
现在,您没有使用任何静态工厂方法,并且只要您的枚举实现一个公共接口,您就具有编译时安全性。
更新:使用新的转换器SPI,它变得更加容易。使用自定义转换器工厂:
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>
Extended from WebMvcConfigurerAdapter
@Override
@SuppressWarnings("unchecked")
public void addFormatters(FormatterRegistry registry) {
registry.addConverterFactory(new ConverterFactory<String, Enum>() {
@Override
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
return source -> {
try {
return (T) Enum.valueOf(targetType, source);
} catch (Exception e) {
return targetType.getEnumConstants()[Integer.parseInt(source)];
}
};
}
});
super.addFormatters(registry);
}