首页 > 其他分享 >springcache condition #result 条件不生效问题排查

springcache condition #result 条件不生效问题排查

时间:2024-01-16 22:16:28浏览次数:25  
标签:缓存 springcache uid 写入 查询 result null condition

本文主要是日常开发过程当中遇到的一个实际问题,以及问题排查的过程

你将了解:

  • springcache 注解中 condition 的作用原理
  • condition 以及 unless 条件判断的区别

背景

有一个用户权限查询接口,查询用户在某个应用的权限,关键的两个入参信息为

  • appCode(应用编码)
  • account(用户账号)

其中在代码逻辑里面需要将用户账号 account 转为用户统一身份id 即 uid 进行内部逻辑处理,由于 account 与 uid 得关系在外部系统存储,因此这里需要缓存 account 与 uid 得关系。缓存时长为2天,如下代码所示:

image-20231209133706834

以上的逻辑预期是缓存 account 与 uid 得关系,无论 uid 是否存在, 不存在的话缓存 null 值(可通过 CacheManager 统一配置)。

但是后续有这样的需求,如果 uid 为 null 得时候不缓存,因此按照 springcache 提供的 condition 条件,按条件缓存。

image-20231209133727717

问题现象

预期的是查询外部系统有数据结果才会缓存account 与 uid得关系,uid结果为 null 得时候并不缓存。但是实际情况是uid有没有结果都不会缓存数据,不符合预期。

排查过程

思考点:

  1. 是不是对 condition 的条件缓存理解得有问题

代码分析

重点关注核心类 CacheInterceptor 拦截器里面对 @Cacheable 注解的解析

CacheInterceptor.invoke() ->CacheAspectSupport.execute() -> private execute()

image-20231209131414314

从上面可知对 @Cacheable 注解的解析在第 2、3 和第 4 步,其中 condition 条件判断再第 2 以及 4 步。

其中第 2 步的findCachedItem 方法中的 conditon 用于判断是否从缓存中查询数据。

image-20231209142336028

第 4 步中的collectPutRequest 方法中的 conditon 用于判断是否要写入缓存,具体实现如下:

image-20231209133615087

通过代码 debug ,发现步骤 2 以及步骤 4 中的 isConditionPassing 的返回值都是 false,因此当我们的配置 condition = "#result !==null' 的结果就是所有的数据都实时查询,查询结果也不会保存至缓存。

查阅资料

通过 spring 的https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/cache.html 关于 springcache 的文档可知,conditon、unless条件是使用 SpEL 表达式实现的。

image-20231209143945252

对于 condition 条件,只对入参进行判断,其中入参能使用的只有 #root 和参数,符合条件的查询入参可以

  • 查询走缓存
  • 缓存没有命中的时候,将实时查询的结果写入缓存

对于 unless 条件,只对出参进行判断,其中出参可以使用 #result 不符合条件的出参可以

  • 缓存没有命中的时候,将实时查询的结果写入缓存

因此,只要将 condition = "#result !==null' 这个条件改为 unless = "#result == null" 就能满足我们的预期:查询走缓存,如果返回结果为 null 则不写入缓存,否则将结果写入缓存。

总结

  1. @Cacheable 注解中,conditon 只对入参进行判断,符合条件的查询先走缓存,缓存没有命中的时候,将实时查询结果写入缓存,否则查询不走缓存并且结果不写入缓存
  2. @Cacheable 注解中,unless 只对出参进行判断,符合条件的不缓存,不符合条件的将结果写入缓存。

该问题的发生是因为自己对 spring cache 相关注解的原理没有深入了解,同时网上有很多错误的例子导致的,因此还是要多看看官方文档以及阅读源码。

标签:缓存,springcache,uid,写入,查询,result,null,condition
From: https://www.cnblogs.com/fisher1994/p/17968618

相关文章

  • SpringCache教程
    前言极大地简化了程序员对于cache的操作流程,可以使用拒接方便的实现,支持redis,Caffeine,Memcached等不同的缓存框架。相关注解名称解释@Cacheable主要针对方法配置,能够根据方法的请求参数对其进行缓存@CacheEvict清空缓存@CachePut保证方法被调用,又希望结果......
  • [论文阅读] Self-conditioned Image Generation via Generating Representations
    Pretitle:Self-conditionedImageGenerationviaGeneratingRepresentationsaccepted:arXiv2023paper:https://arxiv.org/abs/2312.03701code:https://github.com/LTH14/rcgref:https://mp.weixin.qq.com/s/VmyRya2klHpHlJwzMG8JRgref:https://www.zhihu.com/q......
  • Conditional Git Configuration 有条件配置Git信息
    本文学习自Blog本文介绍Git的一个特性,具有潜在的实用性。该特性就是“有条件地为Git项目配置Git信息”。这意味着开发者能根据简单的条件设置,为Git项目仓库自动添加或覆盖添加Git配置信息。下面通过一个简单的例子进行说明。在系统层面的Git配置中,添加如下内容:[includeIf"git......
  • SQL Server报错The datediff function resulted in an overflow
    建模提醒功能异常,获取查询语句到数据库执行报错:Msg535,Level16,State0,Line62Thedatedifffunctionresultedinanoverflow.Thenumberofdatepartsseparatingtwodate/timeinstancesistoolarge.Trytousedatediffwithalessprecisedatepart.消息535,级......
  • @Conditional+@Configuration有没有搞头?
    日拱一卒,功不唐捐。在了解@Conditional之前先花10秒钟复习一下@Configuration这个注解。@Configuration是干什么?是配合@Bean注解来配置Spring容器的bean的。那它为什么会出现呢?因为配置bean的另一种方式是xml,狗都不用。那给个示例看看呗?简单。@Configurationpubl......
  • 无涯教程-Java 正则 - Matcher toMatchResult函数
    java.util.regex.Matcher.toMatchResult()方法将此匹配器的匹配状态作为MatchResult返回。MatchResulttoMatchResult()-声明以下是java.util.regex.Matcher.toMatchResult()方法的声明。publicMatchResulttoMatchResult()MatchResulttoMatchResult()-返回值具有此......
  • [Codeforces] CF1547E Air Conditioners
    CF1547EAirConditioners题目传送门这道题我的思路严重劣于题解思路,所以请慎用但是自认为我的贪心比dp好理解点题意有\(q\)组数据,每组第一排表示有\(n\)个方格和\(k\)个空调,第二排是每个空调的位置\(a_i\),第三排是每个空调的温度\(t_i\)。每个空调对周围的影响......
  • 无涯教程-Java 正则 - MatchResult String group()函数
    java.time.MatchResult.group()方法返回与上一个匹配项匹配的输入子序列。Stringgroup()-声明Stringgroup()Stringgroup()-返回值与上一个匹配项匹配的(可能为空)子序列,为字符串形式。Stringgroup()-异常IllegalStateException-如果尚未尝试匹配,或者上一个匹......
  • 无涯教程-Java 正则 - MatchResult String group(int group)函数
    java.time.MatchResult.group(intgroup)方法返回在上一次匹配操作期间给定组捕获的输入子序列。Stringgroup(intgroup)-声明以下是java.time.MatchResult.group(intgroup)方法的声明。intgroup(intgroup)group  - 该匹配器模式中捕获组的索引。Stringgroup......
  • 无涯教程-Java 正则 - MatchResult int end(int group)函数
    java.time.MatchResult.end(intgroup)方法返回在此匹配期间给定组捕获的子序列的最后一个字符之后的偏移量。intend(intgroup)-声明intend(intgroup)group  - 该匹配器模式中捕获组的索引。intend(intgroup)-返回值最后一个字符匹配后的偏移量。intend(......