2015-08-25 36 views
0

我有一個方法調用另一個@Cacheable方法是這樣的:春天緩存沒有工作瓦特/嵌套方法

public ItemDO findMethod2(long itemId) { 
    this.findMethod1(itemId); 
    ... 
} 

@Cacheable(value = "Item", key="#itemId", unless="#result == null") 
public ItemDO findMethod1(long itemId) { 
    ... 
} 

緩存工作得很好,如果我直接在findMethod1()調用。但是,當我調用findMethod2()時,findMethod1()上的緩存完全被忽略。

難道是由JVM把findMethod1()嵌入到findMethod2()中的技巧嗎?

有沒有人遇到類似的問題?

謝謝!

回答

4

這不是JVM技巧,即findMethod1()沒有在findMethod2()內部內聯或任何此類性質。

的問題是你的代碼繞過「代理」是是建立在你的應用程序類(含findMethod1())爲@Cacheable註釋。

等給出的接口Spring的事務註釋和底層基礎架構,默認情況下春天將創建一個JDK動態代理(AOP風格)爲「攔截」的方法調用,並適用「建議」(如由確定註釋的類型,在這種情況下是緩存)。然而,一旦目標對象從代表目標對象的攔截器(代理)調用以應用建議,則線程現在在目標對象的上下文中執行,因此在目標對象內發生任何後續方法調用直接在目標對象上。

它看起來有點像這樣...

caller -> Proxy -> findMethod2() -> findMethod1() 

理想情況下,你想這是什麼?

caller -> Proxy -> findMethod2() -> Proxy -> findMethod1() 

然而,在線程的上下文中已經執行「目標「對象在findMethod2()之內,所以你最終得到第一個調用堆棧。

春季文檔更好地解釋了它here

該文件繼續指出解決此問題的方法,最有利的是重構代碼以確保調用方正在通過用於第二個方法調用的代理攔截器(即findMethod1())。

我也收集了另一個解決這個問題的方法,就是使用全面的AspectJ,在你的應用程序構建過程中使用編譯器和字節代碼編織器修改實際的目標對象,以便從目標對象內部的後續調用攔截並相應地應用建議。

查看Spring AOP和全AspectJ,以及how to use full AspectJ之間的trade-offs春節文檔在您的Spring應用程序。

希望這會有所幫助。

乾杯!