Spring Force @Cacheable使用putifAbsent代替put [英] Spring force @Cacheable to use putifAbsent instead of put

查看:227
本文介绍了Spring Force @Cacheable使用putifAbsent代替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());
    }
}

请参见

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆