Spring中的动态枚举,或者如何使Spring远离构造函数?

Spring中的动态枚举,或者如何使Spring远离构造函数?,spring,dynamic,enumeration,json-rpc,embeddable,Spring,Dynamic,Enumeration,Json Rpc,Embeddable,“动态枚举”和“静态变量”一样是矛盾修饰法吗?;-) 我只是在春天里泡了很短时间,我想我还没有想到春天。我想要一个类型安全的动态枚举。我将此模式用于事件或错误代码等需要允许后续子类扩展枚举的情况。因为“enum”不能扩展,所以只剩下一个枚举模式类。例如(精简): 公共类事件类型{ 私有字符串名称; 私有静态哈希映射缓存 =新HashMap(); 受保护的事件类型(字符串名称){ if(cache.containsKey(名称)){ 抛出新的RuntimeException(“EventType'

“动态枚举”和“静态变量”一样是矛盾修饰法吗?;-)

我只是在春天里泡了很短时间,我想我还没有想到春天。我想要一个类型安全的动态枚举。我将此模式用于事件或错误代码等需要允许后续子类扩展枚举的情况。因为“enum”不能扩展,所以只剩下一个枚举模式类。例如(精简):

公共类事件类型{
私有字符串名称;
私有静态哈希映射缓存
=新HashMap();
受保护的事件类型(字符串名称){
if(cache.containsKey(名称)){
抛出新的RuntimeException(“EventType'+name+“'已存在!”);
}否则{
this.name=名称;
cache.put(名称,this);
}
}
公共静态AuditEventType解析(字符串名称){
返回cache.get(name);
}
public static final EventType EVENT_START=new AuditEventType(“START”);
公共静态最终事件类型EVENT_END=新的AuditEventType(“END”);
公共静态最终事件类型EVENT_FAIL=新的AuditEventType(“FAIL”);
}
当我将Spring添加到组合中时,问题就开始了。因为它只是一个字符串,所以我将EventType注释为“@Embedded”,使用它的类将该成员注释为“@Embedded”。在使用queryDSL jpa进行查询之前,这似乎工作得很好。DSL将尝试将DB文本转换为EventType,这将导致类型与字符串不匹配。也就是说,我不能说:
WHERE EventType=“Start”
。我通过让具有此类字段的类将其存储为字符串,并将其解析为getter中的EventType对象来解决这个问题(不是很优雅)。所以现在就JPA而言,它只是一个普通的ol'字符串

现在我遇到了服务API的问题。我有一个带有EventType参数的方法。问题是JsonRpcServer类试图通过实例化该字符串将其转换为EventType。这当然会抛出一个“已经存在!”异常

我可能可以用@JsonTypeResolver解决第二个问题(我现在正在阅读)。但所有这些恶作剧都让人感觉不对。这一定是一个共同的问题,必须有更好的解决方案。春季处理此类课程的正确方式是什么?(实际上,它不是一个bean,并且有一个受保护的构造函数)


(我省略了一些关于我们代码使用的一些专有库的细节,这可能不允许我采用“哦,你应该使用‘X’”这样的回答。谢谢你的理解。)

对于Spring方面,请看一下转换服务。这允许您注册自定义转换器。因此,您应该能够注册EventTypeToString Converter和StringToEventTypeConverter。他们将拥有“完全”控制权来解析您的eventtype

对于Hibernate端,可以为EventType使用特定的用户类型,以便Hibernate能够将其作为列值存储和读取。(这正是我希望您需要的) 我有一个类似的要求,每个实体都有一个状态,我不想将其建模为实体本身。
我还没有在查询中直接使用字符串参数,但是有很多接口可以实现,很可能有一个接口允许对参数进行字符串识别

谢谢你的建议,马丁。
conversionService
听起来很有希望。至于用户类型,是的,我已经这样做了(再次感谢StackOverflow!)最后,我需要立即添加
@JsonDeserize(使用=…)
。这很好地防止了JSON-RCP转换试图重新实例化我的静态实例。一旦有机会,我将试用
converionService
并更新线程。再次感谢!
public class EventType {

    private String name;    

    private static HashMap<String, EventType> cache 
                     = new HashMap<String, EventType>();

    protected EventType(String name) {
        if (cache.containsKey(name)) {
            throw new RuntimeException("EventType '" + name + "' already exists!");
        } else {
             this.name = name;
             cache.put(name, this);
        }
    }

    public static AuditEventType parse(String name) {
        return cache.get(name);
    }

    public static final EventType EVENT_START = new AuditEventType("Start");
    public static final EventType EVENT_END   = new AuditEventType("End");
    public static final EventType EVENT_FAIL  = new AuditEventType("Fail");
}