Spring Force @Cacheable使用putifAbsent代替put [英] Spring force @Cacheable to use putifAbsent instead of put
问题描述
我已经按照以下方式实现了Spring缓存
I've Spring cache implemented as below
@Component
public class KPCacheExample {
private static final Logger LOG = LoggerFactory.getLogger(KPCacheExample.class);
@CachePut(value="kpCache")
public String saveCache(String userName, String password){
LOG.info("Called saveCache");
return userName;
}
@Cacheable(value="kpCache")
public String getCache(String userName, String password){
LOG.info("Called getCache");
return "kp";
}
}
和Java Config文件
And Java Config file
@Configuration
@ComponentScan(basePackages={"com.kp"})
public class GuavaCacheConfiguration {
@Bean
public CacheManager cacheManager() {
GuavaCacheManager guavaCacheManager = new GuavaCacheManager("kpCache");
guavaCacheManager.setCacheBuilder(CacheBuilder.newBuilder().expireAfterAccess(2000, TimeUnit.MILLISECONDS).removalListener(new KPRemovalListener()));
return guavaCacheManager;
}
}
默认情况下,spring在缓存接口中使用put方法来更新/放置缓存中的值.我如何强制spring使用putifabsent方法来进行调用,以便如果丢失缓存或在其他病房中使用唯一用户名和密码的方法的第一个请求应返回null,随后对该用户名和密码的后续请求,则可以获取null值应该返回用户名.
By default the spring uses put method in the cache interface to update/put values in the cache. How can I force the spring to use putifabsent method to be invoked, such that I can get null value if cache is missed or in other wards first request to the method with unique username and password should return null and subsequent request to that username and password should return username.
推荐答案
通过Spring的Cache Abstraction源,似乎没有配置设置(开关)默认使用@atomPut以使用原子" putIfAbsent操作.
Well, looking through Spring's Cache Abstraction source, there does not appear to be a configuration setting (switch) to default the @CachePut to use the "atomic" putIfAbsent operation.
您可以使用@CachePut批注的除非(或 condition )属性模拟"putIfAbsent",例如(基于Guava impl)...
You might be able to simulate the "putIfAbsent" using the unless (or condition) attribute(s) of the @CachePut annotation, something like (based on the Guava impl)...
@CachePut(value="Users", key="#user.name" unless="#root.caches[0].getIfPresent(#user.name) != null")
public User save(User user){
return userRepo.save(user);
}
还请注意,我没有测试此表达式,并且使用其他Cache impl时,它不是原子的"或可移植的.表达式(#root.caches [0] .get(#user.name)!= null")可能更便于移植.
Also note, I did not test this expression, and it would not be "atomic" or portable using a different Cache impl. The expression ("#root.caches[0].get(#user.name) != null") maybe more portable.
放弃"atomic"属性可能不是理想的,因此您还可以扩展(Guava)CacheManager以返回自定义" Cache(基于GuavaCache),该缓存将覆盖put操作以委托给"putIfAbsent".
Giving up the "atomic" property may not be desirable so you could also extend the (Guava)CacheManager to return a "custom" Cache (based on GuavaCache) that overrides the put operation to delegate to "putIfAbsent" instead...
class CustomGuavaCache extends GuavaCache {
CustomGuavaCache(String name, com.google.common.cache.Cache<Object, Object> cache, boolean allowNullValues) {
super(name, cache, allowNullValues);
}
@Override
public void put(Object key, Object value) {
putIfAbsent(key, value);
}
}
See the GuavaCache class for more details.
然后...
class CustomGuavaCacheManager extends GuavaCacheManager {
@Override
protected Cache createGuavaCache(String name) {
return new CustomGuavaCache(name, createNativeGuavaCache(name), isAllowNullValues());
}
}
请参见第93行和
See GuavaCacheManager for further details, and specifically, have a look at line 93 and createGuavaCache(String name).
希望这会有所帮助,或者至少会给您带来更多的想法.
Hope this helps, or at least gives you some more ideas.
这篇关于Spring Force @Cacheable使用putifAbsent代替put的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!