@Cacheable的详细介绍,结合redis的操作过程

Spring的缓存抽象

Integration (spring.io)

https://blog.csdn.net/zl1zl2zl3/article/details/110987968

面试官:Spring中的@Cacheable缓存注解,你真的了解吗? - 知乎 (zhihu.com)

Spring Boot 与 缓存 之 自定义 CacheManager

spring cache缓存框架使用

SpringCache的了解与使用

https://blog.csdn.net/qq_33803102/article/details/121138891

简介

  • 自3.1版以来,Spring 框架提供了对透明地向现有 Spring 应用程序添加缓存的支持。与事务支持类似,缓存抽象允许一致地使用各种缓存解决方案,对代码的影响最小。定义了 org.springframework.cache.Cacheorg.springframework.cache.CacheManager 接口来统一不同的缓存技术。并支持使用 JCache(JSR-107)注解简化开发。抽象使得不必编写缓存逻辑但不提供实际的数据存储
  • 缓存的核心思想是当调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存在缓存中,减少数据访问次数和时间,提高性能。
  • 每次调用需要缓存功能的方法时,Spring 会检查指定参数的指定目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户。下次调用直接从缓存中获取。
  • spring cache是spring框架的缓存抽象,集成了各种主流缓存实现(ConcurrentMap、redis、ehcache、Caffeine等)
  • spring默认使用ConcurrentMap作为缓存;如果工程中引入了redis配置,则会使用redis作为缓存spring.cache.type=redis)
  • spring通过CacheManager判断具体使用哪个缓存,每个缓存都有一个具体的CacheManager(比如:EhCacheCacheManager,RedisCacheManager,CaffeineCacheManager),如果没有配置任何的CacheManager,则会使用ConcurrentMap作为缓存

buffer和cache

  • 传统上,缓冲区buffer是一个存储区域,用于暂时保存数据,待数据传输速度对齐后再将数据发送出去。在数据传输过程中,如果数据接收速度较快,数据会被存储在缓冲区中,直到接收方准备好接收为止。它可以用来解决数据传输速度不匹配的问题。

  • 缓存cache会将经常访问的数据复制到更快的存储介质中,如内存,以便在后续访问时无需再从原始数据源获取。这样能够减少数据访问时间,提高性能。

  • 总结

    • 用途不同:缓冲主要用于平衡数据传输速度差异,而缓存主要用于提高数据访问速度。
    • 数据处理:缓冲不对数据进行处理,只是暂时存储,而缓存可以对数据进行处理以满足特定需求。
    • 存储介质:缓冲通常用于暂时存储数据,存储在相同或类似的介质上,而缓存通常将数据存储在更快的存储介质中,如内存。
    • 数据类型:缓冲可以用于各种数据类型,包括传输中的数据,而缓存通常用于经常被访问的数据。

Cache/CacheManager接口

  • Cache接口包含缓存的各种操作集合,操作缓存就是通过这个接口来操作的。
  • Cache 接口下Spring提供了各种 xxxCache 的实现,比如:RedisCacheEhCacheConcurrentMapCache
  • CacheManager 定义了创建、配置、获取、管理和控制多个唯一命名的 Cache。这些 Cache 存在于 CacheManager 的上下文

使用注意点

要使用缓存抽象,需要注意两个方面:

  • 缓存声明: 确定需要缓存的方法及其策略。

  • 缓存配置: 存储数据并从中读取数据的后台缓存。

注解

@EnableCaching

用于开启基于注解的缓存,使用 @EnableCaching 标注在 springboot 主启动类上

@SpringBootApplication
@MapperScan("com.aciu.lambdatest.mapper.**")
@EnableCaching
public class LambdaTestApplication {
 public static void main(String[] args) {
  SpringApplication.run(LambdaTestApplication.class, args);
 }
}

@Cacheable

常用于查询方法,能够根据方法的请求参数对其进行缓存

  • @Cacheable可以标记在方法和类上面。
    • 当标记在方法上表示只对该方法是支持缓存的。
    • 当标记在类上面表示该类的所有方法都会支持缓存的。
    • @Cacheable 不能使用#result,因为这个是返回结果才能使用,但是@Cacheable在执行方法前就要使用key,所以不行
cacheNames/value

声明缓存名字,可以用数组,声明多个缓存

@Cacheable({"books", "isbns"})
public Book findBook(ISBN isbn) {...}
key
  • 声明访问缓存的键,由于缓存本质上是键值存储,因此每次调用缓存方法时都需要使用键去访问。

  • 缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。这个 key 可以使用 spEL 表达式来编写。

  • 这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。

  • @Cacheable(cacheNames="books", key="#isbn")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
    @Cacheable(cacheNames="books", key="#isbn.rawNumber")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
    @Cacheable(cacheNames="books", key="#p0")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
        
    @Cacheable(cacheNames="books", key="#p0.rawNumber")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
  • spEL表达式

    在这里插入图片描述

keyGenerator
  • key 的生成器,key 和 keyGenerator 二选一使用,如果key的编写有固定模式,推荐使用keyGenerator

  • @Cacheable(cacheNames="books", keyGenerator="myKeyGenerator")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
  • @Configuration
    public class CacheConfig implements WebMvcConfigurer {
      @Bean("myKeyGenerator")
      public KeyGenerator keyGenerator(){
          return new KeyGenerator(){
              @Override
              public Object generate(Object target, Method method, Object... params){
                  return method.getName()+"["+ Arrays.asList(params).toString()+"]";
              }
          };
      }
     }
    
cacheManager
  • 可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。或者cacheResolver指定获取解析器。
cacheResolver
  • 即缓存解析器,该属性与cacheManager 是互斥的,只能指定一个。
condition
  • 可以用来指定符合条件的情况下才缓存(condition = “#a0>1”:第一个参数的值>1的时候才进行缓存)

  • @Cacheable(cacheNames="books", condition ="#p0.rawNumber>0")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
unless
  • 否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然也可以获取到结果进行判断。(通过 #result 获取方法结果,如unless="#result==null"声明返回空值不缓存)
sync

在多线程环境中,某些操作可能被同一个参数并发调用(通常在启动时)。默认情况下,缓存抽象不锁定任何内容,相同的值可能会被多次计算,这与缓存的目的背道而驰。

对于这些特殊情况,可以使用 sync 属性指示基础缓存提供程序在计算值时锁定缓存条目。因此,只有一个线程忙于计算值,而其他线程被阻塞,直到条目在缓存中更新。(sync=true)

  • 如果配置了sync为true,只支持配置一个cacheNames,如果配了多个,就会报错:
  • 源码限制
    • 1、不支持unless
    • 2、只能有一个cache
    • 3、不能合并其他与缓存相关的操作

@CachePut

常用于更新/保存方法,会将方法返回值放入缓存

  • 每次都会执行方法,并将结果存入指定的缓存中

  • 同样可以作用于类和方法上

  • 不要在同一个方法上使用@Cacheable和@CachePut

@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor)

@CacheEvict

清空缓存

  • 同样可以作用与类和方法上,依旧有@Cacheable的属性,有额外的allEntriesbeforeInvocation属性
  • 其中,value表示清除操作是发生在哪些Cache上的(对应Cache的名称)
  • key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key
  • condition表示清除操作发生的条件
allEntries

忽略所有的key键,清除所有缓存,这比一个一个清除元素更有效率。

@CacheEvict(cacheNames="books", allEntries=true) 
public void loadBooks(InputStream batch)
beforeInvocation
  • 清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。

  • 使用beforeInvocation可以改变触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

@CacheEvict(cacheNames="books", beforeInvocation=true) 
public void loadBooks(InputStream batch)

@Caching

  • @Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。
  • 有时,需要指定同一类型的多个注释(例如@CacheEvict 或@CachePut) ,因为条件或键表达式在不同的缓存之间是不同的。
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)

@CacheConfig

  • 放在类上,配置该类所有缓存的公共属性,比如设置缓存的名称
  • 它允许共享缓存名称、自定义 KeyGenerator、自定义 CacheManager 和自定义 CacheResolver。将此注释放在类上不会打开任何缓存操作。
@CacheConfig("books") 
public class BookRepositoryImpl implements BookRepository {
    @Cacheable
    public Book findBook(ISBN isbn) {...}
}

代码实操

https://blog.csdn.net/zoroly/article/details/131742671

https://blog.csdn.net/qq359605040/article/details/124469004

代码例子gitee地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: @CacheableSpring框架提供的一个注解,用于将对应的方法的返回结果存储在缓存中,以便下次请求时直接从缓存中获取结果,提高系统性能。 使用Redis作为缓存提供商,可以通过配置Redis作为Cache Manager来实现@Cacheable使用Redis。下面是具体的步骤: 1. 引入依赖:在项目的pom.xml文件中添加Spring框架的相关依赖和Redis的客户端依赖,如spring-boot-starter-data-redis等。 2. 配置Redis:在项目的配置文件中设置Redis的连接信息,包括host、port、password等。可以通过application.properties或application.yml文件进行配置。 3. 创建Redis连接工厂:使用Redis连接信息创建一个Redis连接工厂Bean,用于创建Redis连接。 4. 创建Cache Manager:使用Redis连接工厂创建一个Cache Manager Bean,该Cache Manager将使用Redis作为缓存提供商。 5. 配置@Cacheable注解:在需要使用缓存的方法上添加@Cacheable注解,并指定缓存的名称,如@Cacheable(value = "userCache")。该注解还可以指定缓存的key,以便根据不同的参数生成不同的缓存key。 6. 运行项目:启动项目后,当使用@Cacheable注解修饰的方法被调用时,系统会先检查缓存中是否存在对应的结果。如果存在,则从缓存中获取结果并返回;如果不存在,则调用方法,然后将方法的返回结果存储在缓存中,以供后续使用。 通过以上步骤,可以让@Cacheable注解使用Redis作为缓存提供商,提高系统的性能和响应速度。同时,使用Redis作为缓存存储,还可以实现分布式缓存,增加系统的可扩展性和稳定性。 ### 回答2: @CacheableSpring框架提供的一个注解,用于为方法添加缓存功能。当方法被调用时,如果缓存中存在相应的缓存结果,则直接从缓存中获取,而不会执行方法。如果缓存中不存在相应的缓存结果,则执行方法,并将方法的返回结果存入缓存中,以备后续使用。 当@CacheableRedis结合使用时,可以将返回结果以键值对的形式存储在Redis缓存服务器中。Redis是一种内存数据库,具有快速读写的特点。通过使用Redis作为缓存服务器,可以提高缓存的读写性能。 使用@Cacheable注解时,需配置Redis作为缓存存储的方式。可以通过在Spring的配置文件中指定Redis相关的属性,比如Redis的连接信息、缓存的过期时间等。 在方法被调用时,@Cacheable会先检查Redis中是否存在相应的缓存结果。如果存在,则直接从Redis中读取缓存结果并返回。如果不存在,则执行方法,并将方法的返回结果存储在Redis中,以备后续使用。 使用Redis作为缓存服务器,可以解决传统基于内存的缓存机制的性能瓶颈问题。由于Redis将缓存数据存储在内存中,读写速度快,能够极大地提高应用程序的性能。 综上所述,通过将@CacheableRedis结合使用,可以实现高效的缓存机制,提高系统的响应速度和性能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值