Spring Cache Abstraction:如何处理java.util.Optional <t>

时间:2015-11-02 09:53:44

标签: spring hazelcast

我们的代码库中有很多代码,类似于以下界面:

public interface SomethingService {
    @Cacheable(value = "singleSomething")
    Optional<Something> fetchSingle(int somethingId);

    // more methods...
}

只要我们只使用本地缓存,这就可以正常工作。但是一旦我们使用像Hazelcast这样的分布式缓存,事情就会开始中断,因为java.util.Optional<T>不可序列化,因此无法缓存。

到目前为止我已经解决了这个问题:

  1. 从方法定义中删除java.util.Optional<T>,而不是检查可靠的null
  2. 在缓存实际值之前解开java.util.Optional<T>
  3. 我想避免(1)因为它会涉及大量的重构。而且我不知道如何在不实现自己的org.springframework.cache.Cache的情况下完成(2)。

    我还有其他选择吗?我更喜欢一个适用于大多数分布式缓存的通用(Spring)解决方案(Hazelcast,Infinispan,...),但我也会接受仅限Hazelcast的选项。

1 个答案:

答案 0 :(得分:0)

可能的解决方案是为Optional类型注册序列化程序。 Hazelcast具有flexibile序列化API,您可以为任何类型注册序列化程序。

有关更多信息,请参阅以下示例: https://github.com/hazelcast/hazelcast-code-samples/tree/master/serialization/stream-serializer

这样的事情:

public class OptionalSerializer implements StreamSerializer<Optional> {

@Override
public void write(ObjectDataOutput out, Optional object) throws IOException {
    if(object.isPresent()){
        out.writeObject(object.get());
    }else{
        out.writeObject(null);
    }
}

@Override
public Optional read(ObjectDataInput in) throws IOException {
    Object result = in.readObject();
    return result == null?Optional.empty():Optional.of(result);
}

@Override
public int getTypeId() {
    return 0;//todo:
}

@Override
public void destroy() {

}
}

然而,解决方案并不完美,因为此可选项将成为实际存储的一部分。因此,内部也存储了可选包装器,这可能导致例如问题。查询。