首页 > 其他分享 >SpringBoot2.x系列教程56--SpringBoot中的缓存实现方案介绍

SpringBoot2.x系列教程56--SpringBoot中的缓存实现方案介绍

时间:2022-12-23 18:03:58浏览次数:45  
标签:缓存 SpringBoot -- Spring 56 Cache value key 注解


SpringBoot2.x系列教程56--SpringBoot中的缓存实现方案介绍

作者:一一哥

一. Spring中对缓存的支持

1. Spring Cache简介

从Spring3.1开始,Spring中引入了对Cache的支持。而在Spring Boot中可以通过添加spring-boot-starter-cache缓存依赖,实现缓存功能。

Spring中是通过依赖org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来实现缓存的,我们在Spring Boot中只要通过@EnableCaching注解开启缓存支持,Spring Boot就会根据实现自动配置一个合适的CacheManager。

2. Spring Boot支持的缓存提供商(默认按如下顺序):

Spring Boot中自动检测缓存提供商的默认顺序如下:

  • Generic
  • JCache(JSR-107)(EhCache 3, Hazelcast, Infinispan)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Guava
  • Simple

Spring Boot 为我们提供了多种缓存CacheManager配置方案,默认情况下会使用基于内存map的缓存方案ConcurrenMapCacheManager,内部默认是利用ConcurrentHashMap的来实现缓存。

我们可以通过‘spring.cache.type’属性来强制指定到底使用哪种缓存提供商,如果需要在一些环境(比如,测试)中禁用全部缓存也可以使用该属性。

SpringBoot2.x系列教程56--SpringBoot中的缓存实现方案介绍_User


3. Spring Cache原理

Spring Cache是作用在方法上的,其核心实现逻辑如下:

当我们在调用一个缓存方法时,会把该方法参数和返回结果作为一个键值对存放在缓存中;
等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。
所以在使用Spring Cache的时候,我们要确保缓存的方法的幂等性,也就是对于相同的方法参数要有相同的返回结果。

4. Spring Cache的实现方案

Spring对Cache的实现方案有2种方式,

  • 基于注解配置方式;
  • 基于XML配置方式。

其中基于注解(annotation)的缓存(cache)技术是在Spring 3.1 引入的,它本质上不是一个具体的缓存实现方案(例如 EHCache),而是一个对缓存使用的抽象,通过在已有代码中添加少量关于缓存的注解annotation,就能够达到缓存的效果。

二. Spring Cache注解实现方案详解

1. spring cache中常用缓存注解

  • @Cacheable
  • @CachePut 
  • @CacheEvict
  • @Caching

2. 注解实现方案的特点

  • 通过少量的配置 annotation 注解即可使得已有代码支持缓存;
  • 支持 SpEL 表达式,能使用对象的任何属性或者方法来定义缓存的 key 和 condition;
  • 支持 AspectJ,并通过其实现任何方法的缓存支持;
  • 支持自定义 key 和缓存管理器,具有相当的灵活性和扩展性;
  • 提供开箱即用的缓存临时存储方案;
  • 支持和主流的专业缓存方案(例如Redis)集成。

3. 缓存注解详解

3.1 @Cacheable注解

3.1.1 注解作用

可以作用在方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。

3.1.2 用法举例

单缓存名称:@Cacheable(value=”cache1”)
多缓存名称:@Cacheable(value={”cache1”,”cache2”}

3.1.3 参数介绍

value参数是必须指定的,表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

value:缓存的名称

每一个缓存名称代表一个缓存对象。当一个方法填写多个缓存名称时将创建多个缓存对象。
当多个方法使用同一缓存名称时相同参数的缓存会被覆盖。
所以通常情况我们使用“包名+类名+方法名”或者使用接口的RequestMapping作为缓存名称防止命名重复引起的问题。

key:缓存的 key

key标记了缓存对象中的每一个缓存数据,当我们没有指定该属性时,Spring将使用默认策略生成key,系统会自动按照方法的所有入参生成key,也就是说相同的入参值将会返回同样的缓存结果。

我们也可以利用自定义策略,通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。

如下列无论方法存在多少个入参,只要userName值一致,则会返回相同的缓存结果。

/**
* key 是指传入时的参数
*/
@Cacheable(value="users", key="#id")
public User find(Integer id) {
return null;
}

// 表示第一个参数
@Cacheable(value="users", key="#p0")
public User find(Integer id) {
return null;
}

// 表示User中的id值
@Cacheable(value="users", key="#user.id")
public User find(User user) {
return null;
}

// 表示第一个参数里的id属性值
@Cacheable(value="users", key="#p0.id")
public User find(User user) {
return null;
}

除了上述使用方法的参数作为key之外,Spring还为我们提供了一个root对象用来生成key。

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

// key值为: user中的name属性的值
@Cacheable(value={"users", "xxx"}, key="caches[1].name")
public User find(User user) {
return null;
}

condition:缓存的条件

有的时候我们可能并不希望缓存一个方法的所有返回结果,通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。满足条件后,方法的结果才会被缓存,不填写则认为全部无条件缓存。

使用 SpEL表达式编写条件,返回 true 或者 false,只有为 true 才进行缓存。

#只有用户名长度大于2时参会进行缓存。
@Cacheable(value=”cache1”,condition=”#userName.length()>2”)

3.2 @CachePut注解

3.2.1 注解作用

主要针对方法配置,能够根据方法的请求参数对其结果进行缓存。和 @Cacheable 不同的是,它每次都会触发真实方法的调用,此注解常被用于更新缓存使用。

3.2.2 参数介绍

value:缓存的名称

@CachePut(value=”cache1”)
@CachePut(value={”cache1”,”cache2”}

key:缓存的 key

@CachePut(value=”cache1”,key=”#userName”)

condition:缓存的条件

@CachePut(value=”cache1”,condition=”#userName.length()>2”)

3.3 @CacheEvict注解

3.3.1 注解作用

作用在方法上,根据一定的条件对缓存结果进行清空。

3.3.2 参数介绍

value 缓存的名称

删除指定名称的缓存对象,必须与下面的其中一个参数配合使用:

例如:
@CacheEvict(value=”cache1”)

或者
@CacheEvict(value={”cache1”,”cache2”}

key 缓存的 key

删除指定key的缓存对象。

@CacheEvict(value=”cache1”,key=”#userName”)

condition 缓存的条件

删除指定条件的缓存对象。

@CacheEvict(value=”cache1”,condition=”#userName.length()>2”)

allEntries 方法执行后清空所有的缓存;默认为 false,如果指定为 true,则方法调用后将立即清空所有缓存。

例如:
@CacheEvict(value=”cache1”,allEntries=true)

beforeInvocation 方法执行前清空所有缓存。默认为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存。默认情况下,如果方法执行抛出异常,则不会清空缓存。

例如:
@CacheEvict(value=”cache1”,beforeInvocation=true)

3.4 @Caching注解

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

@Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),@CacheEvict(value = "cache3", allEntries = true) })
public User find(Integer id) {
return null;
}

下一章节中,我将会带大家通过代码实现缓存功能。

 

标签:缓存,SpringBoot,--,Spring,56,Cache,value,key,注解
From: https://blog.51cto.com/u_7044146/5966091

相关文章

  • SpringBoot2.x系列教程36--整合SpringMVC之CORS跨域访问处理(上)
    SpringBoot2.x系列教程36--整合SpringMVC之CORS跨域访问处理(上)作者:一一哥一.跨域问题及解决1.什么是跨域访问?JavaScript出于安全方面的考虑,做了一个同源策略的限制,也就......
  • 解决表单action属性传参时值为null的问题
    一.异常重现最近壹哥有个学生在学习Servlet进行Web开发时,尝试着使用表单中的action传递参数,结果他发现在Servlet中无法接收到前端传过来的参数值。我们先来看看他的代码,具......
  • 关于jsjiami.v6加密和解密
    JavaScript解密是指在JavaScript代码被加密之后,使用特定的工具或方法来恢复其原有的可读性。这种技术通常用于对JavaScript代码进行保护,以防止代码被未经授权的人窃取......
  • 冒泡排序
    冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应......
  • 如何理解动态规划
    一、动态规划三板斧状态转移公式循环或递归性能优化二、WHY1、状态转移公式动态规划与分治不一样,分治的问题是相互独立的,而动态规划的各个状态是有关联关系......
  • 初学java懵了,这个异常是怎么产生的?
    一.异常现象最近壹哥的老表开始学Java啦,结果学了还不到两天,就遇到了他解决不了的问题,然后就跑来问我了。不知有没有其他初学java的小伙伴,大家可以过来围观一下,看看下面的问......
  • 对Integer进行等值比较时踩到的一个坑
    一.引言小伙伴们应该都知道,只要我们写代码,必然就会有BUG的存在。所以解决BUG的过程会伴随程序员的一生,这就是一个无解的常态。在平时的学习和工作过程中,我们需要通过不断地实......
  • BMP格式详解
    BMP文件格式详解(BMPfileformat)BMP文件格式,又称为Bitmap(位图)或是DIB(Device-IndependentDevice,设备无关位图),是Windows系统中广泛使用的图像文件格式。由于它可以不作......
  • 集合泛型不匹配导致的ClassCastException异常解决
    一.代码重现前几天壹哥的一个学生小K编写集合代码时,运行的结果中却出现了一个自己没见过的异常,他不知道怎么解决,于是就跑来找壹哥帮忙。下面就是小K的代码,大家可以来看看,如......
  • 从位图数据取得位图句柄
    #include<windows.h>#include<fstream>usingnamespacestd;voidmain(){ifstreaminfile("bm.bmp",ios::in|ios::binary);BITMAPFILEHEADERbm......