2010-01-13 66 views
2

我有一個使用了Ehcache緩存(但我認爲這個問題是框架無關),用方法攔截所以基本上,如果我記住我的方法來緩存這樣的事情happnes的應用程序:緩存完整性問題

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; 
} 

到目前爲止好。事情我緩存,返回一個Array的方法,並得到這樣調用:

List<Object> result = methodWithCaching(); 
result.add(new Object()); //! 

正如你可以想像,行標有!還更新緩存實例,這不是我想要的。

有人可以想到一種方法來阻止這種行爲,而不修改客戶端,只有攔截器?

回答

0

你是什麼意思「更新緩存」?你是否擔心用戶可以修改methodWithCaching()返回的列表?如果是這樣,我會建議該方法返回一個不可修改的集合。或者,緩存可能會檢測到結果是一個Collection,並用一個不可修改的包裝器來包裝它。

+0

我希望用戶在列表中做任何他們想做的事情。但想象一下這種情況:methodinvocation(1),緩存未命中,userupdates列表和緩存也得到更新。 methodinvocation(2),緩存命中(現在列表包含1個元素),用戶更新列表並且緩存也被更新。 methodinvocation(3),緩存命中(現在列表包含2個元素)等等。 – 2010-01-13 18:28:16

+0

您是否希望用戶擁有緩存對象的本地副本而不是共享實例? – Kevin 2010-01-13 18:37:19

+0

這是正確的,可能沒有修改客戶端,只是攔截器 – 2010-01-13 21:06:24

0

我的理解是,您希望攔截器返回緩存結果的副本,以便任何客戶端修改只會影響副本?

雖然說實話,我想不出一個好的和一般的方法來做到這一點。醜陋的將依靠clone(),或每次創建一個新的列表。

聽起來像你應該真的修改客戶端,如果可能的話。

+0

事情是我不能創建一個新的對象。我肯定不能調用'clone',因爲它是一種受保護的方法。而且返回值可以是任何不只是列表。 – 2010-01-13 18:25:51

+0

正如我所說沒有好的解決方案。 clone()'被設計破壞了;你需要做'if(result instanceof Cloneable)'然後通過反射調用clone()'。 – 2010-01-13 19:27:40