7

シングルトンではない(たとえば、セッションスコープの)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();
    }

}

理想的には、セッションごとに1回UserNameRetriever.getUserName()からユーザー名をフェッチしますが、このコードは実際にはアプリケーション全体をキャッシュします。UserDao

4

3 に答える 3

5

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

とを使用して、メソッドkey="#user.id"のキャッシュを(手動でまたはを使用して@CacheEvict)無効にすることができますが@PreDestroy、キャッシュとセッションデータの2つを混在させない方がよいでしょう。

于 2012-04-14T21:11:56.277 に答える
2

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

あなたの場合、ドロップ@CacheableしてgetUserName()それを置いてくださいUserDao

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

これは、キャッシュのより慣用的な使用法であるだけでなく、保守が容易でパフォーマンスが向上することも証明されます。

元の質問に戻ります。いいえ、これはそのままでは不可能です。あなたはあなた自身を書かなければならないでしょうCacheManager-おそらく既存の実装の周りの

于 2012-04-14T08:25:26.447 に答える
1

私はそれを試していませんが、Springのリファレンスによると、これはうまくいくと思います:

@Cacheable(value = "userName", key = "#root.target")
于 2012-04-14T12:19:00.787 に答える