Spring 强制@Cacheable 使用putifAbsent 而不是put

Spring force @Cacheable to use putifAbsent instead of put

我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 方法来缓存 update/put 中的值。我怎样才能强制 spring 使用 putifabsent 方法被调用,这样我可以在缓存丢失时获得 null 值,或者在其他地方第一次请求具有唯一用户名和密码的方法应该 return null随后对该用户名和密码的请求应该 return username.

嗯,查看 Spring 的缓存抽象源,似乎没有配置设置(开关)来默认 @CachePut 使用 "atomic" putIfAbsent 操作。

您可以使用 unless(或 condition)属性来模拟 "putIfAbsent" @CachePut 注释,类似于(基于 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);
}

另请注意,我没有测试此表达式,它不会 "atomic" 或使用不同的 Cache impl 可移植。表达式 ("#root.caches[0].get(#user.name) != null") 可能更便携。

放弃 "atomic" 属性 可能并不可取,因此您还可以将 (Guava)CacheManager 扩展为 return 一个 "custom" 缓存(基于 GuavaCache)覆盖 put 操作委托给 "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。

然后...

class CustomGuavaCacheManager extends GuavaCacheManager {

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

GuavaCacheManager for further details, and specifically, have a look at line 93 and createGuavaCache(String name)

希望这对您有所帮助,或者至少能给您一些更多的想法。