Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 缓存完整性问题_Java_Caching_Pass By Reference_Ehcache - Fatal编程技术网

Java 缓存完整性问题

Java 缓存完整性问题,java,caching,pass-by-reference,ehcache,Java,Caching,Pass By Reference,Ehcache,我有一个使用ehcache进行缓存的应用程序(但我认为这个问题与框架无关),它有一个方法拦截器,所以基本上如果我将我的方法标记为缓存,就会发生如下情况: public Object invoke(MethodInvocation mi) throws Throwable { Object result = cache.get(key); //key comes from MethodInvocation processing if (result

我有一个使用ehcache进行缓存的应用程序(但我认为这个问题与框架无关),它有一个方法拦截器,所以基本上如果我将我的方法标记为缓存,就会发生如下情况:

public Object invoke(MethodInvocation mi) throws Throwable {
        Object result = cache.get(key); 
        //key comes from MethodInvocation processing
        if (result == null) {
            result = mi.proceed();
            cache.put(key, result);
        }
        return result;
}
到目前为止还不错。我正在缓存一个方法,该方法返回一个
数组
,调用方式如下:

List<Object> result = methodWithCaching();
result.add(new Object()); //!
List result=methodWithCaching();
结果。添加(新对象());/!
可以想象,标有
的行还更新缓存实例,这不是我想要的


有人能想出一种方法来停止这种行为而不修改客户端,只修改拦截器吗?

你说的“更新缓存”是什么意思?您是否担心用户可以修改methodWithCaching()返回的列表?如果是这样,我建议该方法返回一个不可修改的集合。或者,缓存可能会检测到结果是一个集合,并使用不可修改的包装将其包装。

我的理解是,您希望拦截器返回缓存结果的副本,以便任何客户端修改都只会影响副本

老实说,我想不出一个好的、通用的方法来做到这一点。丑陋的是依赖于
clone()
,或者每次都创建一个新列表


听起来你真的应该修改客户端,如果可能的话。

问题是我不能创建新对象。我当然不能调用
clone
,因为它是受保护的方法。而且返回值可以是任何东西,而不仅仅是列表。正如我所说,没有好的解决方案<代码>克隆()
被设计破坏;您需要执行
if(result instanceof Cloneable)
操作,然后通过反射调用
clone()
。我希望用户可以对列表执行任何操作。但是想象一下这个场景:methodinvocation(1),cache miss,userupdates列表,并且缓存也得到更新。methodinvocation(2),缓存命中(现在列表包含1个元素),用户更新列表,缓存也得到更新。methodinvocation(3)、cache hit(现在列表包含2个元素)等等。您希望用户拥有缓存对象的本地副本而不是共享实例吗?没错,而且可能在不修改客户端的情况下,只是interceptorI会尝试使用akhnaten建议的Cloneable实现某些东西。你要么返回数据的副本,要么同时返回不同的数据结构。我不能。实现
Cloneable
不会使
clone()
方法公开。我必须在我想要缓存的每个对象中自己实现这一点