修改Ehcache缓存中取到的值,缓存中的值也被修改了
问题现象
我们从Ehcache中取出缓存的对象,之后将对象中的属性进行了修改使用。等再次从缓存中拿到对象后,发现对象的值变成了上一次调用修改后的对象了。
原因
Ehcache中缓存的是原对象的引用,所以引用的内容被修改后cache内部的值也会被修改。
解决方案
使用Ehcache的copyStrategy
【修改Ehcache缓存中取到的值,缓存中的值也被修改了】Ehcache提供了copyOnRead="true" copyOnWrite="true"的配置属性。
作用是在读取或写入数据时,不使用原始数据,而是使用拷贝数据。
但是在使用该配置的时候,还要提供copyStrategy class属性,提供Copy策略。
copy策略类
public class EhcacheCopyStrategy implements ReadWriteCopyStrategy {
@Override
public Element copyForWrite(Element value) {
if(value != null){
Object temp=(Serializable)value.getObjectValue();
try {
return new Element(value.getObjectKey(),deepCopy(temp));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return value;
}
@Override
public Element copyForRead(Element storedValue) {
if(storedValue != null){
Object temp=(Serializable)storedValue.getObjectValue();
try {
return new Element(storedValue.getObjectKey(),deepCopy(temp));
} catch (ClassNotFoundException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return storedValue;
} privateObject deepCopy(Object src) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
return in.readObject();
}
}
使用immutable对象
将我们的实体类设计成immutable的,如果需要修改就创建一个新的对象。
如何构建一个immutable对象
- 确保fields中的成员都被private final修饰;private保证内部成员不会被外部直接访问,final保证成员在初始化后不会被assigned。
- 不提供改变成员的方法,例如setXxx。
- 使用final修饰自定义的类,确保类中的方法不会被重写。
- 如果类中的某个成员是mutable类型的,那么在初始化该成员或者企图用get方法从外部对其观察时,应该使用深度拷贝,确保immutable。
StringBuilder类的对象是mutable的数据类型,当一个StringBuilder对象被创建出来之后,其内部的值是可以通过某些内部方法进行改变的。
推荐阅读
- 利用构建缓存机制缩短Docker镜像构建时间
- MFC修改编辑框光标显示位置方法详解
- sqlserver数据库加密后无法使用MDF|sqlserver数据库加密后无法使用MDF,LDF,log文件名称被修改的数据恢复
- Java编程伪共享与缓存行填充
- 高并发底层原理|高并发之伪共享和缓存行填充(缓存行对齐)(@Contended)
- SpringBoot整合缓存支持
- Win11右键菜单怎么修改为传统Win10右键风格()
- 如何优雅的修改node_modules中的依赖库
- Navicat|Navicat 16 for MySQL 修改注册表 永久试用
- ng-alain安装