Caffeine配合Spring Cache的基本使用

本地缓存介绍

缓存在日常开发中启动至关重要的作用,由于是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力。例如Redis 这种 NoSql数据库作为缓存组件,它能够很好的作为分布式缓存组件提供多个服务间的缓存,但是 Redis 这种还是需要网络开销,增加时耗。本地缓存是直接从本地内存中读取,没有网络开销,例如秒杀系统或者数据量小的缓存等,比远程缓存更合适。

Caffeine缓存组件介绍

按 Caffeine Github 文档描述,Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后,spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件。Caffeine作为当下本地缓存的王者被大量应用在各个实际项目中,可以有效的提高服务的吞吐量、qps、降低rt。

整合过程

配置

依赖
<!--Spring的 @Cacheable等注解相关-->
<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>                
缓存管理器的配置
/**
* 定义缓存管理器,配合Spring Cache的注解使用
* @return
*/
@Bean
public CacheManager cacheManager() {
    CaffeineCacheManager cacheManager = new CaffeineCacheManager();
    cacheManager.setCaffeine(Caffeine.newBuilder()
            //设置过期时间
            .expireAfterAccess(5, TimeUnit.MINUTES)
            //设置初始化容量
            .initialCapacity(10)
            //设置最大容量
            .maximumSize(100));
    return cacheManager;
}

请注意,除了使用上述方式配置缓存管理器外,还可以通过配置文件的形式配置(推荐),通过配置文件的形式如下

spring:
  cache:
    type: caffeine
    caffeine:
      spec: initialCapacity=10,maximumSize=100,expireAfterWrite=5m   //参数所代表的意义如上配置类等价

使用

配置完毕后,我们就可以在项目中使用本地缓存了。

缓存使用示例

使用缓存前,我们还需要在项目的启动类上加上 @EnableCaching注解,表示启动缓存。

1、@Cacheable

这个注解用于修饰方法,当我们访问该注解修饰的方法时,若缓存存在则返回缓存,若缓存不存在,则执行方法,并将方法的返回结果放入缓存。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Cacheable {
    @AliasFor("cacheNames")
    String[] value() default {};

    @AliasFor("value")
    String[] cacheNames() default {};

    String key() default "";
	....
}

以上是该注解最重要的三个属性,其中cacheName和value等价,cacheName可以理解为缓存key的前缀(类似于redis中缓存key的order:userId的order:)。当key不设置值时,默认使用方法参数进行初始化,注意key为SpEl表达式,因此如果key写为字符串时,需要单引号括起来。如下为一个简单的使用示例。

/**
     * 类比redis:
     * cacheName + key = redisKey(redis中的缓存key)
     * 方法返回结果: key对应的缓存值
     * @param age 参数
     * @return
     */
    @Cacheable(key = "#age",cacheNames = "cache")
    public String getCache(int age) {
        return  "get"+age+"--->" + UUID.randomUUID().toString().substring(6);
    }

例如我们传的age为11,那么缓存的key就为 cache::11。除了以上的属性外,该注解还有condition属性比较常用,用于判断缓存保存的条件。

@Cacheable(key = "#age",cacheNames = "cache",condition = "#age % 2 == 0")
public String getCache(int age) {
     return  "get"+age+"--->" + UUID.randomUUID().toString().substring(6);
 }

上面这个情况,当age为偶数时,才会走缓存,否则不走缓存,也就不会写入缓存。
还有一个unless属性作用和condition相反,请自行测试。

2、@CachePut

不管当前缓存有没有,都将方法的返回结果加入缓存。不用多说,大家就知道这个注解常用于修改数据时,更新缓存的场景。

 /**
     * 不管缓存有没有,都写入缓存
     * @param age
     * @return
     */
    @CachePut(key = "#age",cacheNames = "cache")
    public String putCache(int age) {
        return  "put"+age+"--->" + UUID.randomUUID().toString().substring(6);
    }
3、@CacheEvict

这个注解用于删除缓存

/**
     * 根据cacheName和key使缓存失效,即删除缓存
     * @param age
     * @return
     */
    @CacheEvict(key = "#age",cacheNames = "cache")
    public String delCache(int age) {
        return  "del"+age+"--->" + UUID.randomUUID().toString().substring(6);
    }
4、@Caching

在实际的项目场景中,常常需要我们修改多个缓存,对于这个场景,我们就需要用到@Caching注解了,他可以用来组合多个注解。

/**
     * caching实现组合注解,添加缓存,并失效其他缓存
     * @param age
     * @return
     */
    @Caching(cacheable = @Cacheable(cacheNames = "caching",key = "#age"),evict = @CacheEvict(cacheNames = "t1",key = "#age"))
    public String caching(int age) {
        return  "caching"+age+"--->" + UUID.randomUUID().toString().substring(6);
    }

以上代码就是组合操作:

  • 从caching::age缓存取数据,缓存不存在时,向缓存放数据
  • 失效缓存t1:age
5、出现异常时,缓存会怎么样

以上的几种情况都是正常工作的场景,当方法抛出异常时,这个缓存的表现会如何呢?

/**
  * 用于测试异常情况
  * @param age
  * @return
  */
 @Cacheable(cacheNames = "cache",key = "#age")
 public int testE(int age) {
     return 100/age;
 }

经过实测,当age == 0时,以上代码的缓存不会成功。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值