Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何告诉Spring cache不要在@Cacheable注释中缓存空值_Spring_Caching_Memcached - Fatal编程技术网

如何告诉Spring cache不要在@Cacheable注释中缓存空值

如何告诉Spring cache不要在@Cacheable注释中缓存空值,spring,caching,memcached,Spring,Caching,Memcached,有没有一种方法可以指定,如果该方法返回null值,那么对于这样的方法,不将结果缓存在@Cacheable注释中 @Cacheable(value="defaultCache", key="#pk") public Person findPerson(int pk) { return getSession.getPerson(pk); } 更新: 以下是去年11月提交的关于缓存空值的JIRA问题,该问题尚未解决: 更新对于Spring 3.2和更高版本,此答案现在已经过时,请参见技术旅行,

有没有一种方法可以指定,如果该方法返回null值,那么对于这样的方法,不将结果缓存在@Cacheable注释中

@Cacheable(value="defaultCache", key="#pk")
public Person findPerson(int pk) {
   return getSession.getPerson(pk);
}
更新: 以下是去年11月提交的关于缓存空值的JIRA问题,该问题尚未解决:

更新对于Spring 3.2和更高版本,此答案现在已经过时,请参见技术旅行,OP:随时将其标记为已接受

我认为这是不可能的(即使Spring中有条件缓存逐出,可以在方法调用之后执行,而
@cacheexecute
参数beforeInvocation设置为false,这是默认值)检查
CacheAspectSupport
类表明,返回值没有存储在
InspectAfterCacheExecutes(ops.get(execute))之前的任何位置呼叫

protected Object execute(Invoker invoker, Object target, Method method, Object[] args) {
    // check whether aspect is enabled
    // to cope with cases where the AJ is pulled in automatically
    if (!this.initialized) {
        return invoker.invoke();
    }

    // get backing class
    Class<?> targetClass = AopProxyUtils.ultimateTargetClass(target);
    if (targetClass == null && target != null) {
        targetClass = target.getClass();
    }
    final Collection<CacheOperation> cacheOp = getCacheOperationSource().getCacheOperations(method, targetClass);

    // analyze caching information
    if (!CollectionUtils.isEmpty(cacheOp)) {
        Map<String, Collection<CacheOperationContext>> ops = createOperationContext(cacheOp, method, args, target, targetClass);

        // start with evictions
        inspectBeforeCacheEvicts(ops.get(EVICT));

        // follow up with cacheable
        CacheStatus status = inspectCacheables(ops.get(CACHEABLE));

        Object retVal = null;
        Map<CacheOperationContext, Object> updates = inspectCacheUpdates(ops.get(UPDATE));

        if (status != null) {
            if (status.updateRequired) {
                updates.putAll(status.cUpdates);
            }
            // return cached object
            else {
                return status.retVal;
            }
        }

        retVal = invoker.invoke();

        inspectAfterCacheEvicts(ops.get(EVICT));

        if (!updates.isEmpty()) {
            update(updates, retVal);
        }

        return retVal;
    }

    return invoker.invoke();
}
受保护对象执行(调用程序调用程序、对象目标、方法、对象[]参数){
//检查是否启用了方面
//以应对自动拉入AJ的情况
如果(!this.initialized){
返回invoker.invoke();
}
//获得后备班
Class targetClass=aopproxutils.ultimateTargetClass(目标);
if(targetClass==null&&target!=null){
targetClass=target.getClass();
}
最终集合cacheOp=GetCacheOperationsSource().getCacheOperations(方法,targetClass);
//分析缓存信息
如果(!CollectionUtils.isEmpty(cacheOp)){
Map ops=createOperationContext(cacheOp、方法、参数、目标、targetClass);
//从驱逐开始
检查缓存收回之前(操作获取(收回));
//后续可缓存
CacheStatus status=inspectCacheables(ops.get(CACHEABLE));
Object retVal=null;
映射更新=检查缓存更新(ops.get(UPDATE));
如果(状态!=null){
如果(需要状态更新){
更新.putAll(状态.cUpdates);
}
//返回缓存对象
否则{
returnstatus.retVal;
}
}
retVal=invoker.invoke();
检查收回(操作获取(收回));
如果(!updates.isEmpty()){
更新(更新,检索);
}
返回返回;
}
返回invoker.invoke();
}

万岁,从Spring 3.2开始,框架允许使用Spring SPEL和
实现这一点,除非
。java文档中关于可缓存的注释:

公共抽象字符串,除非

用于否决方法缓存的Spring表达式语言(SpEL)属性

与condition()不同,此表达式是在调用方法后计算的,因此可以引用结果。默认值为“”,这意味着缓存永远不会被否决

重要的方面是
,除非在调用方法后对
进行评估。这非常有意义,因为如果密钥已经在缓存中,则该方法将永远不会执行

因此,在上面的示例中,您可以简单地注释如下(#result可用于测试方法的返回值):

我可以想象,这种情况是由于使用可插拔缓存实现(如Ehcache)而产生的,Ehcache允许缓存空值。根据您的用例场景,这可能是可取的,也可能不是可取的。

@Cacheable(value="defaultCache", key="#pk",unless="#result!=null")
不起作用,您可以尝试:

@CachePut(value="defaultCache", key="#pk",unless="#result==null")

这对我很有用。

嗨,我想你应该接受Tech Trip的答案,因为它与当前版本的Spring更相关。嗨,我有一个场景,redis缓存服务器缓存异常。我必须避免将异常缓存到服务器。我可以为此使用“除非”参数吗?是否可以在“除非”中提及例外情况?请分享你的建议。非常感谢JSR107提供了一种机制,可以始终调用带注释的方法,并且仍然通过cacheResult#skipGet缓存结果。根据skipGet上的API,如果为true,则也会跳过对抛出异常的调用前检查。但是,如果在调用过程中抛出异常,它将按照标准异常缓存规则进行缓存,因此可能无法满足您的需要。然而,使用JSR107,您可以显式地排除配置上的某些异常,这可能会让您有继续的余地。(参见NonCacheXceptions)Spring的抽象提供了JSR107注释支持。仅供其他人参考-还有一个
条件
参数,也可以使用。在我的例子中,我需要
condition=“#pk!=null”
,这样当参数为
null
时,缓存不会抛出
hv000028:isvalid调用期间出现意外异常
:)我复制粘贴了您的代码,发现出现了意外错误(type=Internal Server error,status=500)。为缓存操作返回的Null键(可能您在没有调试信息的类上使用命名参数?)Builder[public java.util.mappover@tftd建议使用条件=“#pk!=Null”。如果您需要使用“sync”作为“除非”在使用“sync”时不起作用,这很有用。您的意思是
除非=“#result==Null”
?除非结果否则缓存!=null\u表示如果结果==null,则缓存。因此,正确的表达式是
除非=“\result==null”
这表示除非结果否则缓存==null,这表示如果结果,则缓存!=null。
@CachePut(value="defaultCache", key="#pk",unless="#result==null")