【问题标题】:Spring force @Cacheable to use putifAbsent instead of putSpring 强制 @Cacheable 使用 putifAbsent 而不是 put
【发布时间】:2015-06-03 08:05:06
【问题描述】:

我的 Spring 缓存实现如下

@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 配置文件

@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 方法被调用,这样如果缓存丢失或在其他情况下,我可以获得空值,第一次请求具有唯一用户名和密码的方法应该返回空值,随后对该用户名和密码的请求应该返回用户名。

【问题讨论】:

    标签: spring guava spring-cache


    【解决方案1】:

    好吧,通过 Spring 的 Cache Abstraction 源代码,似乎没有配置设置(开关)来默认 @CachePut 使用“原子”putIfAbsent 操作。

    您也许可以使用 @CachePut 注释的 unless(或 condition)属性来模拟“putIfAbsent”,类似于(基于番石榴实现)...

    @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") 可能更便携。

    放弃“原子”属性可能是不可取的,因此您还可以扩展 (Guava)CacheManager 以返回一个“自定义”缓存(基于 GuavaCache),该缓存覆盖放置操作以委托给“putIfAbsent”。 .

    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);
        }
    }
    

    有关更多详细信息,请参阅GuavaCache 类。

    那么……

    class CustomGuavaCacheManager extends GuavaCacheManager {
    
        @Override
        protected Cache createGuavaCache(String name) {
            return new CustomGuavaCache(name, createNativeGuavaCache(name), isAllowNullValues());
        }
    }
    

    更多详情请参阅GuavaCacheManager,具体而言,请查看line 93createGuavaCache(String name)

    希望这会有所帮助,或者至少能给你一些想法。

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 2017-04-08
      • 2015-02-25
      • 1970-01-01
      • 2016-02-29
      • 2019-12-02
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      相关资源
      最近更新 更多