[英]Can Spring's @Cacheable annotation have the same scope as the annotated method's bean?
Is there an easy way to use Spring's @Cacheable
annotation with a non-singleton (eg session-scoped) bean and have the cache have the same scope as said bean? 是否有一种简单的方法可以将Spring的@Cacheable
注释与非单例(例如会话范围的)bean一起使用,并且缓存与所述bean具有相同的范围?
Example: 例:
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();
}
}
Ideally, UserNameRetriever.getUserName()
would fetch the username from the UserDao
once per session, but this code actually caches application-wide. 理想情况下, UserNameRetriever.getUserName()
会在每个会话中从UserDao
一次用户名,但此代码实际上会缓存应用程序范围内的用户名。
If you want a session cache, use the session. 如果需要会话缓存,请使用会话。 That is, store the user in a private field in the session-scoped bean, or access the HttpSession
object directly. 也就是说,将用户存储在会话范围的bean中的私有字段中,或直接访问HttpSession
对象。 @Cacheable
is generally meant for application-wide resources. @Cacheable
通常用于应用程序范围的资源。
Well, you can use key="#user.id"
, and to invalidate the cache (manually or with @CacheEvict
) on a @PreDestroy
method, but it would be better if you don't mix the two - caching and session data. 好吧,你可以使用key="#user.id"
,并在@PreDestroy
方法上使缓存(手动或使用@CacheEvict
)无效,但如果你不混合两个 - 缓存和会话数据会更好。
I think you are approaching the problem from the wrong side. 我认为你是从错误的一方接近问题。 Instead of having " local " session-scoped caches storing only one value have one global cache storing a map from user name to User
values. 不是存储仅存储一个值的“ 本地 ”会话范围的缓存,而是具有一个全局缓存,其存储从用户名到User
值的映射。
In your case drop @Cacheable
on getUserName()
and put it on UserDao
: 在你的情况下,在getUserName()
上删除@Cacheable
并将其放在UserDao
:
public class UserDao {
@Cacheable("users")
public User getUserByLogin(String user) {
//...
}
}
Not only this is more idiomatic usage of cache, but also it will prove to be easier to maintain and better performing. 这不仅是缓存的惯用用法,而且它将更容易维护和更好的性能。
Back to your original question: no, this is not possible out-of-the-box. 回到原来的问题:不,这不是开箱即用的。 You would have to write your own CacheManager
- probably a decorator around existing implementation. 您必须编写自己的CacheManager
- 可能是围绕现有实现的装饰器 。
我没有尝试过,但根据Spring参考,我认为这样可行:
@Cacheable(value = "userName", key = "#root.target")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.