2012-04-14 11 views
5

Springの@Cacheable注釈を非シングルトン(例えば、セッションスコープ)Beanと使い、キャッシュに前記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

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

これは)動作しますが、 ( \t \ @CacheEvict(値= "userNameに" なしのメモリリーク、キー= "#1 root.target" を有する \t \ @PreDestroy \t公共ボイドクリーンアップ(){ \t} ) また、@Cacheableを使用しないことに決めました。なぜなら、値が一度だけ計算されることを保証するものではないからです。 –

+0

メモリリークの意味は?キャッシュが大きすぎます。 @Cacheableはまずキャッシュ内を検索するので、キャッシュ内にまだ値が計算されないことが保証されます。 – sinuhepop

+0

セッションが終了すると、値はキャッシュに残っていますが、アクセスできなくなるため、メモリリークです。 @PreDestroyは、セッションが終了したときにキャッシュされた値が確実に追い出されるようにします。 –

2

あなたは間違った側から問題に近づいていると思います。 「ローカル」の代わりに、1つの値のみを格納するセッションスコープキャッシュには、ユーザー名からUser値までのマップを格納する1つのグローバルキャッシュがあります。あなたのケースでは

getUserName()@Cacheableをドロップし、UserDaoの上に置く:

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

だけでなく、これはキャッシュのより慣用使い方ですが、また、それがパフォーマンスを維持しやすく、より良いとなるだろう。

元の質問に戻ってください:いいえ、これはすぐに使用することはできません。既存の実装の周りにCacheManager - おそらくと書く必要があります。私はそれを試していないが、Spring referenceによると、私はこれが仕事だと思う

+0

RE:あなたが間違った側から問題に近づいていると思います.UserDaoは外部システムからユーザーを取得します。ユーザーはセッション中一貫性を持たせたいが、前記外部システムにおいて変更されている。あなたのアプローチはこの動作を示さないでしょう。 –

3

セッション・キャッシュが必要な場合は、セッションを使用します。つまり、セッションスコープのBeanのプライベートフィールドにユーザーを格納するか、オブジェクトHttpSessionに直接アクセスします。 @Cacheableは、一般的にアプリケーション全体のリソースを対象としています。

さて、あなたはkey="#user.id"を使用することができ、キャッシュを無効にするために(手動または@CacheEvict付き)@PreDestroy方法で、しかし、あなたは2つの混在していない場合はそれが良いだろう - キャッシュとセッションデータを。

+0

こんにちは@Bozhoは、Spring WebアプリケーションでhttpsessionとCacheableを使用する方が良いと思われる理由を正当化できますか? –

+0

それはアプリケーション全体のリソース対セッション全体です。セッションリソースに@Cacheableを使用する場合は、さらに努力します。 – Bozho

関連する問題