我们的代码库中有很多代码类似于以下界面:
public interface SomethingService {
@Cacheable(value = "singleSomething")
Optional<Something> fetchSingle(int somethingId);
// more methods...
}
只要我们只使用本地缓存,这就可以正常工作。但是一旦我们使用像 Hazelcast 这样的分布式缓存,事情就开始崩溃了,因为 java.util.Optional<T>
不可序列化,因此无法缓存。
到目前为止我已经提出来解决这个问题:
- 删除
java.util.Optional<T>
从方法定义中检查可信赖的null
. - 展开
java.util.Optional<T>
在缓存实际值之前。
我想避免 (1),因为它会涉及大量重构。而且我不知道如何在不实现我自己的情况下完成 (2) org.springframework.cache.Cache
.
我还有哪些其他选择?我更喜欢适用于大多数分布式缓存(Hazelcast、Infinispan 等)的通用(Spring)解决方案,但我也接受仅 Hazelcast 的选项。
最佳答案
一个潜在的解决方案是为 Optional 类型注册一个序列化程序。 Hazelcast 有一个灵活的序列化 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() {
}
}
但是这个解决方案并不完美,因为这个可选的东西将成为实际存储的一部分。所以在内部也存储了 Optional 包装器,这可能会导致问题,例如查询。
关于Spring 缓存抽象 : How to Deal With java. util.Optional<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33474867/