Spring Cache简明教程

Spring Cache简明教程

  • 引言
  • 什么是Spring Cache?
    • 核心特性
    • 应用场景
    • 如何工作
  • 如何使用
    • 1. 添加依赖
    • 2. 启用缓存
    • 3. 配置缓存
    • 4. 使用缓存注解
  • 使用缓存的注意事项
    • 缓存的数据序列化
    • 缓存键的生成
    • 缓存内容的一致性
    • 缓存的并发问题
    • 缓存穿透
    • 缓存雪崩
    • 缓存的存储容量
    • 方法的可见性和返回类型
    • 事务性操作和缓存
  • 总结

引言

  在我上一篇文章如何正确使用缓存来提升系统性能中,我从偏理论的视角介绍了Cache在性能优化中的必要性,在这篇文章中我们介绍Spring全家桶中和cache相关Spring-Cache。

什么是Spring Cache?

  Spring Cache是Spring框架提供的一个抽象层,专注于提供一种透明的方式来添加缓存功能到Spring应用程序中。它不是一个具体的缓存实现,而是提供了一套创建和管理缓存的标准,并能够与多种缓存实现无缝集成,例如Ehcache、Caffeine、Redisson等。

核心特性

  以下是Spring Cache的一些核心特性:

  • 声明式缓存抽象:通过Java注解,开发者可以声明性地控制方法的缓存行为,而无需编写具体的缓存逻辑。
  • 无需改变代码结构:缓存逻辑通过AOP增强被注解的方法,因此不需要修改方法的实际代码。
  • 支持多种缓存库:与多个流行的缓存库兼容,开发者可以根据自身需求选择最适合的缓存解决方案。
  • 灵活的缓存配置:可以通过配置文件灵活地管理缓存行为,包括缓存的名称、过期时间和条件等。
  • 动态缓存决策:支持在运行时根据方法执行的上下文动态地做出缓存决策。

应用场景

  Spring Cache适用于以下应用场景:

  • 提高性能:对于那些计算成本高昂或者频繁访问的数据,通过缓存可以显著提高系统的响应速度。
  • 减少数据库压力:缓存可以减少数据库的读操作,对于读多写少的场景特别有用。
  • 提高系统可扩展性:通过使用分布式缓存,可以在不增加数据库负荷的情况下,横向扩展应用程序。

如何工作

  Spring Cache背后的工作原理基于Spring AOP(面向切面编程),它会在运行时动态地创建代理对象,来拦截对被注解方法的调用。根据注解的不同,Spring Cache可以执行如下操作:

  • @Cacheable:在方法执行前先检查缓存,如果缓存中已经存在相应的数据,则直接返回缓存数据而不执行方法。
  • @CachePut:无论如何都会执行方法,并将执行结果放入指定的缓存中。
  • @CacheEvict:删除缓存中的数据,通常用于删除操作或数据更新后的缓存同步。
  • @Caching:组合多个缓存操作,可以同时使用以上几种注解。

通过上述机制,Spring Cache提供了一个简单而强大的缓存管理能力,使得开发者能够专注于业务逻辑的实现,而将缓存的维护交给框架去处理。

如何使用

1. 添加依赖

  我们拿SpringBoot Maven的项目为例,说下如何在项目中使用Spring Cache,首先很简单,需要在pom文件中引入Spring Cache相关的依赖。

<dependencies><!-- 添加Spring Boot Cache Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><!-- 如果使用特定的缓存实现,如Caffeine --><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId></dependency>
</dependencies>

2. 启用缓存

  另外还需要在Spring Boot应用程序的主类或任何配置类上使用@EnableCaching注解来启用缓存支持。

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@EnableCaching
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

3. 配置缓存

  虽然Spring Boot为许多缓存实现提供了自动配置,但你也可以通过application.properties或application.yml文件进行自定义配置。例如,如果你使用Caffeine作为缓存实现,可以按以下方式配置:

# application.properties
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s

当然你也可以通过代码的形式定义CacheManager,实现对Cache的配置,代码如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager("cache1", "cache2");cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES));return cacheManager;}
}

4. 使用缓存注解

  在服务中,你可以通过在方法上添加相应的缓存注解来实现缓存逻辑。

  • 使用@Cacheable来缓存方法的返回结果。
import org.springframework.cache.annotation.Cacheable;public class SomeService {@Cacheable("cache1")public SomeObject getSomeObject(String id) {// 方法实现,如果缓存中有对应id的对象,则不执行此代码return fetchFromDatabase(id);}
}
  • 使用@CachePut来更新缓存。
import org.springframework.cache.annotation.CachePut;public class SomeService {@CachePut(value = "cache1", key = "#someObject.id")public SomeObject updateSomeObject(SomeObject someObject) {// 方法实现,总是执行并刷新缓存return saveToDatabase(someObject);}
}
  • 使用@CacheEvict来清除缓存。
import org.springframework.cache.annotation.CacheEvict;public class SomeService {@CacheEvict(value = "cache1", key = "#id")public void deleteSomeObject(String id) {// 方法实现,删除对象的同时清除缓存removeFromDatabase(id);}
}

你还可以使用@Caching来组合多个缓存操作。

使用缓存的注意事项

  使用Spring Cache时,需要注意以下几个关键点:

缓存的数据序列化

  当使用分布式缓存或需要将缓存数据存储在磁盘上时,数据序列化变得非常重要。你需要确保你的对象可以被序列化和反序列化,否则会抛出异常。对于复杂对象,考虑使用JSON或其他自定义序列化策略,当你不指定序列化策略时,默认会使用java序列化,这时候就要求你必须实现Serializable接口。

缓存键的生成

  默认情况下,Spring Cache使用方法参数的hashCode()equals()方法来生成缓存键。如果你的方法参数是自定义的对象,确保这些方法被适当地覆盖。你也可以通过实现KeyGenerator接口或使用key属性自定义键的生成。

缓存内容的一致性

  缓存数据可能会与数据库中的数据不一致。当数据被更新或删除时,你需要使用@CachePut@CacheEvict注解来确保缓存与数据源保持同步。

缓存的并发问题

  虽然缓存操作通常是原子性的,但在高并发环境下仍然可能遇到并发问题。例如,多个线程可能同时计算同一个缓存缺失的值。为了避免这种情况,你可能需要使用锁或其他同步机制。

缓存穿透

  缓存穿透是指查询不存在的数据。因为缓存不会存储这样的数据,所以每次查询都会打到后端数据库,从而可能造成数据库的压力。为了预防这种情况,可以采用布隆过滤器或者将查询结果为空的情况也缓存起来。

缓存雪崩

  缓存雪崩指在缓存失效后,大量的请求同时到达数据库,可能会导致数据库瞬时压力过大。为了防止这种情况,可以设置不同的缓存过期时间,使用缓存预热策略,或者实施熔断限流措施。

缓存的存储容量

  对于本地缓存,缓存的大小应当根据可用内存合理配置,避免内存溢出。对于分布式缓存,应当考虑其存储容量和扩展性。

方法的可见性和返回类型

  @Cacheable本身逻辑也是基于SpringAOP实现的,所以需要和其他缓存注解一样应用于公共方法。对私有方法、final方法或类、static方法使用缓存注解是无效的,因为Spring的AOP无法拦截这些方法的调用。同样,缓存方法的返回类型应该是非null值,因为大多数缓存实现都不会存储null值。如果方法可能返回null,那么需要进行额外的处理来避免缓存穿透。

事务性操作和缓存

  如果在事务性操作中使用缓存,需要注意事务的传播行为和缓存操作的顺序。错误的操作顺序可能会导致缓存与数据库状态不一致。

总结

  本文详细介绍了Spring Cache的使用和注意事项。Spring Cache作为Spring框架提供的缓存抽象,允许通过声明式注解轻松地在应用中集成缓存,以此提升性能和减少开发时间。以下是本文关键点的总结:

  1. Spring Cache不是缓存实现:它提供了一组与缓存实现无关的接口和注解。
  2. 简单的集成步骤:包括添加依赖、启用缓存、配置缓存以及在方法上使用缓存注解。
  3. 缓存注解的使用:介绍了@Cacheable@CachePut@CacheEvict等注解的使用场景。
  4. 注意事项
    • 数据序列化:确保对象可以被序列化和反序列化。
    • 缓存键生成:覆盖hashCode()equals()或自定义键的生成。
    • 缓存内容一致性:使用注解确保缓存与数据源同步。
    • 并发问题:可能需要锁或其他同步机制。
    • 缓存穿透:使用布隆过滤器或缓存空查询。
    • 缓存雪崩:设置不同的缓存过期时间,缓存预热策略,或实施熔断限流。
    • 缓存容量:合理配置本地缓存大小,考虑分布式缓存的存储容量和扩展性。
    • 方法的可见性:缓存注解应用于公共方法。
    • 事务性操作:注意事务的传播行为和缓存操作的顺序。

备注:本文使用了部分AI生成内容,作者已对有效性做了校验,请放心查阅。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/655075.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp组件库Card 卡片 的使用方法

目录 #平台差异说明 #基本使用 #配置卡片间距 #配置卡片左上角的缩略图 #配置卡片边框 #设置内边距 #API #Props #Slot #Event 卡片组件一般用于多个列表条目&#xff0c;且风格统一的场景。 #平台差异说明 AppH5微信小程序支付宝小程序百度小程序头条小程序QQ小程…

基于STM32的以太网通信协议选择与实现

在基于STM32的以太网通信中&#xff0c;主要涉及到选择合适的通信协议和实现对应的功能代码。常见的通信协议包括TCP/IP、UDP、HTTP等&#xff0c;选择合适的协议取决于具体应用需求。以下将介绍在STM32上进行以太网通信时&#xff0c;常用的通信协议选择以及对应功能代码的实现…

CSDN·COC城市开发者组织2023年度聚会上海站纪实

目录 前言活动宣传活动议程活动总结结束语 前言 2023年是CSDNCOC成立之年&#xff0c;经过一年的不断发展和壮大&#xff0c;COC上海城市开发者社区的队伍不断壮大&#xff0c;本着每个月都有线下活动的原则&#xff0c;先后举办大大小小的线下沙龙活动20余场。与此同时&…

洛谷p1157组合的输出

组合的输出 题目描述 排列与组合是常用的数学方法&#xff0c;其中组合就是从 n n n 个元素中抽出 r r r 个元素&#xff08;不分顺序且 r ≤ n r \le n r≤n&#xff09;&#xff0c;我们可以简单地将 n n n 个元素理解为自然数 1 , 2 , … , n 1,2,\dots,n 1,2,…,n&a…

NRZ Modulation

NRZ Modulation 正文简介NRZ 的优势 正文 简介 全称不归零 non-return to zero(NRZ) 调制。代表了使用两个信号等级的一种逻辑信号。一个等级为 1&#xff0c;一个等级为 0。负电压对应逻辑电路中的 0&#xff0c;正电压对应逻辑电路中的 1。对于 NRZ 传输&#xff0c;波特率…

trucksim三车队列仿真 matlab一直闪退问题

Trucksim2019 matlab版本2023a 基本框架应该都清楚 下图是主界面 overlay videos and polots with other runs 模块是 关联另一个车辆模型 核心是下图标红是核心 Number of vehicle codes 选择ALL 不要选

如何解决云计算中的性能和延迟问题?

随着云计算的普及&#xff0c;越来越多的企业开始将业务迁移到云端。然而&#xff0c;随着业务的发展和数据量的增长&#xff0c;云计算中的性能和延迟问题也逐渐凸显出来。这些问题不仅会影响用户体验&#xff0c;还会对企业的业务发展造成负面影响。因此&#xff0c;如何解决…

第1章 领域驱动设计的背景和来源

第1章 领域驱动设计的背景和来源 1-1 DDD课程导学1-2 DDD的核心思想和解决的痛点问题1-3 面向对象和敏捷与DDD的区别与联系1-4 DDD的过去、现在与未来 1-1 DDD课程导学 所以大家好&#xff0c;我是尤达&#xff0c;欢迎来到我们深入领域驱动设计。 这门课程。 从我们的副标题结…

世微AP5151芯片低压差 线性降压 恒流驱动IC 台灯 指示灯 矿灯

概述 AP5151 是一种低压差、线性降压、 固定输出电流的 LED 恒流驱动器。 除 LED 外&#xff0c;AP5151 无需外接其它元 器件即可构成一个恒流输出的 LED 驱动 电路。 AP5151 内置过热保护功能&#xff0c;可有效 保护芯片&#xff0c;避免结温超过 120oC 时因过热 而造成损坏…

java后端远程调用文件上传接口(multipart/form-data类型)的方法

multipart/form-data是一种用作传输多个文件/表单项的数据格式。 一、http请求配置 /*** HttpClientConfig http请求配置*/ public class HttpClientConfig {/*** 连接时间 ms*/protected int CONNECT_TIMING_OUT 300000;/*** 请求响应时间 ms*/protected int RESPONSE_TIMI…

【图形学】双三次贝塞尔曲线绘制方法

双三次贝塞尔曲线的定义 双三次贝塞尔曲面是由16个控制点定义的曲面&#xff0c;通常表示为4x4矩阵。 曲面的公式如下&#xff1a; p ( u , v ) ∑ i 0 3 ∑ j 0 3 P i , j B i , 3 ( u ) B j , 3 ( v ) , ( u , v ) ∈ [ 0 , 1 ] [ 0 , 1 ] p(u,v)\sum_{i0}^3\sum_{j0}…

【程序员英语】【美语从头学】初级篇(入门)(笔记)Lesson10(电话会话Ⅱ)

《美语从头学初级入门篇》 注意&#xff1a;被 删除线 划掉的不一定不正确&#xff0c;只是不是标准答案。 文章目录 Lesson 10 Telephone Conversation Ⅱ 电话会话&#xff08;二&#xff09;会话A会话B笔记I would like to do&#xff08;Id like to to do&#xff09;我想…

如何从视频号中提取视频的文案?抖音文案也可提取

最近不少小伙伴刷抖音看看视频一个一个的进行抄&#xff0c;太慢了。​今天分享一个工具搞定怎么提取视频文案的方法&#xff01; 提取文案小助手 提取文案小助手是专注视频创作者的利器&#xff0c;帮助用户一键提取视频号中的文案&#xff0c;获取的方式比较简单&#xff0c…

知过去,预未来,相信AI计算的力量

过去几十年来&#xff0c;人工智能&#xff08;AI&#xff09;领域取得了巨大的进展&#xff0c;从最初的概念逐渐演变为影响各个行业的核心技术。回顾过去&#xff0c;我们可以看到AI计算在推动科技创新和社会变革方面的无可比拟的力量。而更为令人振奋的是&#xff0c;这种力…

Sui TVL跻身全链前十名|全面详解Sui原生功能如何促使DeFi蓬勃发展

根据DefiLlama数据显示&#xff0c;1月28日Sui TVL超过4.02亿美元&#xff0c;跻身所有区块链TVL前十名&#xff01; Sui的创新应用原生功能为DeFi应用铺平了道路&#xff0c;为用户提供了良好的体验。每个原生功能&#xff0c;从促进高效的共享流动性到简化用户互动&#xff0…

js中contextmenu、click和mousedown的区别在哪?

contextmenu、click和mousedown的定义 contextmenu&#xff1a;在鼠标右键点击时触发。可以在此事件中执行特定的操作&#xff0c;比如显示自定义的右键菜单或者阻止浏览器默认的上下文菜单弹窗。它是为了满足特定场景下对右键点击的定制化处理需求。 click事件是通用的鼠标点…

印章制作办法

印章制作办法&#xff1a; 最近在做单位技术支持的培训&#xff0c;需要增加个培训章&#xff0c;自己内容完成即可。 一、excel表格中 &#xff0c;插入-形状-圆&#xff08;按住shift按键&#xff09; 操作三步&#xff1a; 1.填充 无 &#xff1a; 2.形状轮廓 ---“红色…

Linux之常见的管理命令

目录 1. whoami 2. hostname 3. uname 4. date 5. alias 6. history 7. sudo 8. systemctl 9. ps 1. whoami 作用&#xff1a; 显示出当前有效的用户名称语法&#xff1a;whoami(选项)选项&#xff1a; --help&#xff1a;在线帮助--version&#xff1a;显示版本信息…

CF1920F1 Smooth Sailing (Easy Version) 题解

魔幻暴力题。 题意简述 给你一张 n m n\times m nm 的地图&#xff0c;每个点是海 .&#xff0c;岛屿 # 或者火山 v。保证岛屿和非岛屿均可以形成恰好一个四连通块且岛屿不与地图边界接壤&#xff0c;至少有一个岛屿点与一个火山点。 定义一条合法的路径为&#xff0c;从一…

代码随想录算法训练营day15|104.二叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数 104.二叉树的最大深度 &#xff08;优先掌握递归&#xff09; 什么是深度&#xff0c;什么是高度&#xff0c;如何求深度&#xff0c;如何求高度&#xff0c;这里有关系到二叉树的遍…