2012-04-14 77 views
5

有沒有使用Spring的@Cacheable註解與非單(如會話範圍)bean並緩存具有相同的範圍,因爲說豆一種簡單的方法?Spring的@Cacheable註釋與註釋方法的bean有相同的作用域嗎?

實施例:

import javax.inject.Inject; 
import javax.inject.Named; 

import org.springframework.cache.annotation.Cacheable; 
import org.springframework.context.annotation.Scope; 
import org.springframework.security.core.context.SecurityContextHolder; 

@Named 
@Scope("session") 
public class UserNameRetriever { 

    @Inject private UserDao userDao; 

    @Cacheable("userName") 
    public String getUserName() { 
     return userDao.getUserByLogin((String)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getName(); 
    } 

} 

理想情況下,將UserNameRetriever.getUserName()取從UserDao每一次會話的用戶名,但是這個代碼實際上緩存應用程序範圍內。

回答

2

我還沒有嘗試過,但根據Spring reference我認爲這會工作:

@Cacheable(value = "userName", key = "#root.target") 
+0

此工作,但有內存泄漏而不 ( \t \ @CacheEvict(值= 「username」 的,鍵= 「#root.target」) \t \ @PreDestroy \t公共無效清理(){ \t} ) 另外,我已經決定不畢竟使用@Cacheable,因爲它不保證該值將只計算一次。 – 2012-04-16 19:28:54

+0

內存泄漏是什麼意思?也許你的緩存太大了。 @Cacheable將首先在緩存中查找,因此它保證在仍處於緩存中時不會計算該值。 – sinuhepop 2012-04-16 19:59:46

+0

這是內存泄漏,因爲一旦會話結束,該值仍在緩存中,但無法訪問。 @PreDestroy確保會話結束時緩存的值被清除。 – 2012-04-16 20:11:27

2

我認爲你是從錯誤的方向靠近的問題。相反,具有「當地」會話範圍的緩存存儲只有一個值有一個全局高速緩存存儲從用戶名的地圖User值。

在你的情況在getUserName()下降@Cacheable並把它放在UserDao

public class UserDao { 
    @Cacheable("users") 
    public User getUserByLogin(String user) { 
    //... 
    } 
} 

這不僅是高速緩存的更地道的用法,但它也將被證明是更容易維護和性能更好。

回到你原來的問題:沒有,這是不可能出的即裝即用。您必須編寫自己的CacheManager - 可能是現有實現的

+0

RE:我認爲你是從錯誤的方向靠近的問題:userDAO的獲取來自外部系統的用戶,我想要的用戶名(僅適用於化妝品中使用)是整個會議上一致,但在一個新的會話,如果刷新它在所述外部系統中已經改變。你的方法不會表現出這種行爲。 – 2012-04-16 19:36:49

3

如果你想有一個會話緩存,使用的會話。也就是說,將用戶存儲在會話範圍的bean中的私有字段中,或者直接訪問對象。 @Cacheable通常用於應用程序範圍的資源。

那麼,您可以使用key="#user.id",並在@PreDestroy方法上使緩存無效(手動或使用@CacheEvict),但如果不混合兩個緩存和會話數據會更好。

+0

您好@Bozho請問您爲什麼認爲在春季Web應用程序中使用httpsession vs Cacheable更好? – 2015-08-31 14:47:59

+0

它是整個會話範圍內的應用程序範圍資源。如果您想使用@Cacheable來獲取會話資源,則需要付出額外的努力 – Bozho 2015-09-01 19:57:56

相關問題