SpringCache缓存

简介: SpringCache缓存

一:为什么需要缓存

前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。

使用缓存是一个很“高性价比”的性能优化方式,尤其是对于有大量重复查询的程序来说。通常来说,在WEB后端应用程序来说,

耗时比较大的往往有两个地方:

1、查数据库;

2、调用其它服务的API(因为其它服务最终也要去做查数据库等耗时操作);

重复查询也有两种:

1、我们在应用程序中代码写得不好,写的for循环,可能每次循环都用重复的参数去查询了。

2、大量的相同或相似请求造成的。比如资讯网站首页的文章列表、电商网站首页的商品列表、微博等社交媒体热搜的文章等等,当大量的用户都去请求同样的接口,同样的数据,如果每次都去查数据库,那对数据库来说是一个不可承受的压力。所以我们通常会把高频的查询进行缓存,我们称它为“热点”

二:SpringCache介绍

存有诸多的好处,于是大家就摩拳擦掌准备给自己的应用加上缓存的功能。但是网上一搜却发现缓存的框架太多了,各有各的优势,比如==Redis[中央缓存-远程缓存]==、Memcached、Guava、Caffeine[本地缓存]等等。

如果我们的程序想要使用缓存,就要与这些框架耦合。聪明的架构师已经在利用接口来降低耦合了,利用面向对象的抽象和多态的特性,做到业务代码与具体的框架分离。

但我们仍然需要显式地在代码中去调用与缓存有关的接口和方法,在合适的时候插入数据到缓存里,在合适的时候从缓存中读取数据。想一想「AOP」的适用场景,这不就是天生就应该AOP去做的吗?

自Spring 3.1起,提供了类似于 @Transactional 注解事务的注解Cache支持,且提供了Cache抽象,在此之前一般通过AOP实现

使用springcache的好处:

  • 提供基本的Cache抽象,方便切换各种底层Cache;
  • 通过注解Cache可以实现类似于事务一样,缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码就可以完成;
  • 提供事务回滚时也自动回滚缓存;
  • 支持比较复杂的缓存逻辑;

所以说 Spring Cache就是一个缓存框架。它利用了AOP(将缓存逻辑与服务逻辑解耦),实现了基于注解的缓存功能(声明式缓存),并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了。而且Spring Cache也提供了很多默认的配置,用户可以快速将缓存集成到项目中;

三: springcache注解

3.1:@Cacheable注解

==如果缓存中没有:查询数据库,存储缓存,返回结果,==

==如果缓存中有:直接返回结果==

作用:可以用来进行缓存的写入,将结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法。 最简单的使用方式,注解名称=缓存名称,使用例子如下:

@Service
@CacheConfig(cacheNames = "role")//提取缓存的前缀配置
public class RoleServiceImpl implements IRoleService {
 
    @Autowired
    private RoleMapper roleMapper;
 
    /**
     * <p>
     * 几个属性:
     * a)cacheNames/value:指定缓存组件的名字
     *      cacheNames = {"role"}可以使用多个参数,是数组的形式,可以指定多个缓存
     * b)key:缓存数据使用的key,可以用他来指定。默认是使用方法参数的值
     *      编写SpEl:   #id  #a0,#po,#argrs[0]  "0"代表参数的索引
     *      #result  方法执行后的返回值
     *      #root.methodName   方法名
     *      key = "#root.methodName+'['+#id+']'"
     * e)condition:指定符合缓存的条件
     *      condition = "#id>0 and #root.methodName eq 'aaa'" 可以多条件判断
     * f)unless: 否定缓存,当unless的条件为true,方法结果不会被缓存,可以获取结果进行判断
     *      unless = "#result==null",结果为null,就不缓存
     */
    @Override
    //@Cacheable(cacheNames = "role", key = "#id",condition = "#id>0",unless = "#result==null")
    @Cacheable(key = "#id",condition = "#id>0",unless = "#result==null")
    public Role findById(Integer id) {
        return roleMapper.selectByPrimaryKey(id);
    }
  
    @Cacheable(key ="#root.method.getName()")//直接引用mehtodname异常
    @Override
    public R findAllRole() {
        List<Role> roleList = roleMapper.findAll();
        return R.ok(roleList);
    }
}
3.2:@CacheEvict注解

@CacheEvict:删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置allEntries=true时,可以对整个条目进行批量删除

  /**
     * .@CacheEvict 缓存清除
     *  key:指定要清除的数据
     */
    @Override
    @CacheEvict(key = "#id")
    public Integer delete(Integer id) {
        return roleMapper.deleteByPrimaryKey(id);
    }
3.3:@CachePut注解

@CachePut:当需要更新缓存而不干扰方法的运行时 ,可以使用该注解。也就是说,始终执行该方法,并将结果放入缓存

本质上说,如果存在对应的缓存,则更新覆盖,不存在则添加;

/**
     * .@CachePut既调用方法、又更新数据,达到同步更新缓存
     * <p>
     * 运行时机:
     * 1、先调用目标方法 ★★★
     * 2、将目标方法的结果缓存起来★★★
     * 条件:存取Id的key要保持一致
     *     key = "#role.id"     传入员工的Id
     *     key = "#result.id"   使用返回员工的Id
     * 注意: @Cacheable不能使用#result
     *      因为 @Cacheable在目标方法执行之前需要得到这个key,所以不能用#result
     */
@Override
@CachePut(key = "#result.id")//更新或者添加缓存---》有则更新,无则添加
public Role update(Role role) {
  roleMapper.updateByPrimaryKey(role);
  return role;
}
3.4:@Caching注释

在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况.而@Caching可以实现,对于复杂的缓存策略,我们可借助SpEL实现;

Spring Cache提供了一些供我们使用的SpEL上下文数据,下表直接摘自Spring官方文档:

 /**
     * .@Caching 定义复杂缓存规则
     */
    @Override
    @Caching(
            cacheable = {
                    @Cacheable(key = "#role.rolename")
               
            },
            put = {
                    @CachePut(key = "#role.id"),
                    @CachePut(key = "#role.rolecode")
            },
            evict = {
                    @CacheEvict(key = "8")
            }
    )
    public R add(Role role) {
//        role.setId(null);
        try {
            roleMapper.insert(role);
        } catch (Exception e) {
            return R.error();
        }
        return R.ok(role.getId());
    }
3.5:注解小结

对于缓存声明,spring的缓存提供了一组java注解:

  • @Cacheable
  • 功能:触发缓存写入,如果缓存中没有,查询数据库,存储缓存,返回结果,如果缓存中有,直接返回结果
  • 应用:查询数据库方法,且查询的数据时热点数据
  • @CacheEvict
  • 功能:触发缓存清除
  • 应用:删除或修改数据库方法
  • @CachePut
  • 功能:缓存写入(不会影响到方法的运行)。有则更新,无则添加
  • 应用:新增到数据库方法
  • @Caching
  • 功能:重新组合要应用于方法的多个缓存操作
  • 应用:上面的注解的组合使用
  • @CacheConfig(cacheNames = "xxx")
  • 功能:可以提取公共的缓存key的前缀,一般是业务的前缀
  • 应用:作用在类之上
相关文章
|
28天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
4天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
452 17
|
7天前
|
JSON 自然语言处理 数据管理
阿里云百炼产品月刊【2024年9月】
阿里云百炼产品月刊【2024年9月】,涵盖本月产品和功能发布、活动,应用实践等内容,帮助您快速了解阿里云百炼产品的最新动态。
阿里云百炼产品月刊【2024年9月】
|
20天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
8天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
392 3
|
22天前
|
人工智能 IDE 程序员
期盼已久!通义灵码 AI 程序员开启邀测,全流程开发仅用几分钟
在云栖大会上,阿里云云原生应用平台负责人丁宇宣布,「通义灵码」完成全面升级,并正式发布 AI 程序员。
|
24天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2603 22
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
6天前
|
存储 人工智能 搜索推荐
数据治理,是时候打破刻板印象了
瓴羊智能数据建设与治理产品Datapin全面升级,可演进扩展的数据架构体系为企业数据治理预留发展空间,推出敏捷版用以解决企业数据量不大但需构建数据的场景问题,基于大模型打造的DataAgent更是为企业用好数据资产提供了便利。
300 2
|
5天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
106 65
|
24天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1582 17
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码