Spring的@Cacheable注解是否可以与带注解的方法的bean具有相同的作用域?

1l5u6lss  于 2023-08-02  发布在  Spring
关注(0)|答案(4)|浏览(116)

有没有一种简单的方法可以将Spring的@Cacheable注解与非单例(例如:session-scoped)bean,并该高速缓存具有与所述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获取用户名一次,但这段代码实际上是在应用程序范围内缓存的。

0h4hbjxa

0h4hbjxa1#

如果需要会话缓存,请使用会话。也就是说,将用户存储在会话作用域bean的私有字段中,或者直接访问HttpSession对象。@Cacheable通常用于应用程序范围的资源。
当然,您可以使用key="#user.id",并在@PreDestroy方法上该高速缓存无效(手动或使用@CacheEvict),但最好不要将两者混合在一起-缓存和会话数据。

f8rj6qna

f8rj6qna2#

我还没有尝试过,但根据Spring参考,我认为这可以工作:

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

字符串

hiz5n14c

hiz5n14c3#

我认为你从错误的Angular 来处理这个问题。与只存储一个值的“local”会话范围缓存不同,它有一个全局缓存,用于存储从用户名到User值的Map。
在本例中,将@Cacheable放在getUserName()上,然后将其放在UserDao上:

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

字符串
这不仅是缓存的惯用用法,而且将证明它更容易维护和更好的性能。
回到你最初的问题:不,这是不可能的开箱即用。您必须编写自己的CacheManager-可能是围绕现有实现编写的decorator

t0ybt7op

t0ybt7op4#

您可以创建带有Session(如果您只希望用于请求)范围的CacheManagerbean。它工作得很好。

@Bean
  @SessionScope
  public CacheManager requestCacheManager() {
    return new ConcurrentMapCacheManager();
  }

字符串
考虑限制/设置缓存的边界(正如一些ppl提到的内存“泄漏”),所以你可以尝试使用CaffeineCacheManager,在那里你可以设置最大大小,过期ttl等。

相关问题