Caffeine简介

Caffeine是一个高性能,高命中率,低内存占用,near optimal 的本地缓存,简单来说它是 Guava Cache 的优化加强版

依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
   <groupId>com.github.ben-manes.caffeine</groupId>
   <artifactId>caffeine</artifactId>
</dependency>

开启缓存

@EnableCaching注解开启使用缓存管理功能

@SpringBootApplication
@EnableCaching
public class Application {

   public static void main(String[] args) {
       SpringApplication.run(Application.class, args);
  }

}

注入

方式一

  1. 新建一个枚举类

public enum Caches {
   CACHE_ACCESS_TOKEN(10, 7200);

   /** 最大数量 */
   private Integer maxSize;

   /** 过期时间 秒 */
   private Integer ttl;

   Caches() {
  }

   Caches(Integer maxSize, Integer ttl) {
       this.maxSize = maxSize;
       this.ttl = ttl;
  }

   public Integer getMaxSize() {
       return maxSize;
  }

   public Integer getTtl() {
       return ttl;
  }

}
  1. 注入到IOC容器

    /**
    * 本地缓存
    * @return
    */
   @Bean
   @Primary
   public CacheManager cacheManager() {
       SimpleCacheManager simpleCacheManager = new SimpleCacheManager();

       ArrayList<CaffeineCache> caffeineCaches = new ArrayList<>();

       for (Caches c : Caches.values()) {
           caffeineCaches.add(new CaffeineCache(c.name(),
                           Caffeine.newBuilder()
                                  .recordStats()
                                  .expireAfterWrite(c.getTtl(), TimeUnit.SECONDS)
                                  .maximumSize(c.getMaxSize())
                                  .build()
                  )
          );
      }

       simpleCacheManager.setCaches(caffeineCaches);
       return simpleCacheManager;

  }

方式二

@Bean
@Primary
public CacheManager cacheManager() {

   CaffeineCacheManager caffeineCacheManager = new CaffeineCacheManager();
   Caffeine<Object, Object> caffeine = Caffeine.newBuilder().expireAfterWrite(60, TimeUnit.MINUTES);
   caffeineCacheManager.setCaffeine(caffeine);
   return caffeineCacheManager;

}

使用

可以使用spring提供的@Cacheable、@CachePut、@CacheEvict等注解来方便的使用caffeine缓存

@Cacheable(cacheNames = "CACHE_ACCESS_TOKEN", key = "#root.methodName")
public String getAccessToken(String corpid, String corpsecret) {

  //todo something...
  return "";

}

问题

使用@Cacheable缓存不起作用

失效场景

  • 在私有方法上加缓存

  • 类内部方法调用加缓存

失效原因

Spring cache 的实现原理是基于 AOP 的动态代理实现的:即都在方法调用前后去获取方法的名称、参数、返回值,然后根据方法名称、参数生成缓存的key(自定义的key例外),进行缓存。

AOP 不支持对 private 私有方法的拦截,所以也就不支持私有方法上的 Spring Cache 注解。

this 调用不是代理对象的调用, 所以 AOP 失效,注解失效。

解决办法

  1. 方法用 public 限定符修饰;

  2. 类内部方法调用加缓存时可以用 SpringContextUtil 获取当前 Bean ,由它来调用

工具类

SpringContextUtil

@Component
public class SpringContextUtil implements ApplicationContextAware {

   public static ApplicationContext applicationContext;

   public void setApplicationContext(ApplicationContext applicationContext) {
       SpringContextUtil.applicationContext = applicationContext;
  }

   public static Object getBean(String name) {
       return applicationContext.getBean(name);
  }

   public static <T> T getBean(Class<T> clazz) {
       return applicationContext.getBean(clazz);
  }

   public static <T> T getBean(String name, Class<T> clazz) {
       return applicationContext.getBean(name, clazz);
  }

   public static Boolean containsBean(String name) {
       return applicationContext.containsBean(name);
  }

   public static Boolean isSingleton(String name) {
       return applicationContext.isSingleton(name);
  }

   public static Class<? extends Object> getType(String name) {
       return applicationContext.getType(name);
  }


}
 

Spring Cache + Caffeine实现本地缓存的更多相关文章

  1. spring boot:使用spring cache+caffeine做进程内缓存(本地缓存)(spring boot 2.3.1)

    一,为什么要使用caffeine做本地缓存? 1,spring boot默认集成的进程内缓存在1.x时代是guava cache 在2.x时代更新成了caffeine, 功能上差别不大,但后者在性能上 ...

  2. Spring集成GuavaCache实现本地缓存

    Spring集成GuavaCache实现本地缓存: 一.SimpleCacheManager集成GuavaCache 1 package com.bwdz.sp.comm.util.test; 2 3 ...

  3. 使用Spring Cache + Redis + Jackson Serializer缓存数据库查询结果中序列化问题的解决

    应用场景 我们希望通过缓存来减少对关系型数据库的查询次数,减轻数据库压力.在执行DAO类的select***(), query***()方法时,先从Redis中查询有没有缓存数据,如果有则直接从Red ...

  4. Caffeine Cache-高性能Java本地缓存组件

    前面刚说到Guava Cache,他的优点是封装了get,put操作:提供线程安全的缓存操作:提供过期策略:提供回收策略:缓存监控.当缓存的数据超过最大值时,使用LRU算法替换.这一篇我们将要谈到一个 ...

  5. springboot之本地缓存(guava与caffeine)

    1. 场景描述 因项目要使用本地缓存,具体为啥不用redis等,就不讨论,记录下过程,希望能帮到需要的朋友. 2.解决方案 2.1 使用google的guava作为本地缓存 初步的想法是使用googl ...

  6. JAVA缓存规范 —— 虽迟但到的JCache API与天生不俗的Spring Cache

    大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 有诗云"纸上得来终觉浅,绝知 ...

  7. Spring Cache缓存技术的介绍

    缓存用于提升系统的性能,特别适用于一些对资源需求比较高的操作.本文介绍如何基于spring boot cache技术,使用caffeine作为具体的缓存实现,对操作的结果进行缓存. demo场景 本d ...

  8. Spring Cache缓存框架

    一.序言 Spring Cache是Spring体系下标准化缓存框架.Spring Cache有如下优势: 缓存品种多 支持缓存品种多,常见缓存Redis.EhCache.Caffeine均支持.它们 ...

  9. Spring Cache扩展:注解失效时间+主动刷新缓存

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  10. 使用guava cache在本地缓存热点数据

    某些热点数据在短时间内可能会被成千上万次访问,所以除了放在redis之外,还可以放在本地内存,也就是JVM的内存中. 我们可以使用google的guava cache组件实现本地缓存,之所以选择gua ...

随机推荐

  1. .Net后台调用js,提示、打开新窗体、关闭当前窗体

    .Net后台调用js,提示.关闭当前窗体.打开新窗体 Response.Write("<script>window.alert('支付成功!');window.open('/Jk ...

  2. RStuido Server 选择不同的 R 版本(conda 中的不同 R 版本)

    自从上一次服务器重装系统之后,总感觉缺少了一些东西,安装R包很多依赖库报错,也可以解决,但总是存在,烦. 一天,一个同事问我说ggpubr包安装不成功,我就自己试了一下,真的是--安装不成功. 当你到 ...

  3. 万字长文讲透 RocketMQ 4.X 消费逻辑

    RocketMQ 是笔者非常喜欢的消息队列,4.9.X 版本是目前使用最广泛的版本,但它的消费逻辑相对较重,很多同学学习起来没有头绪. 这篇文章,笔者梳理了 RocketMQ 的消费逻辑,希望对大家有 ...

  4. 经纬度坐标为中心点生成米距离长度半径的圆形面,含java js源码+在线绘制,代码简单零依赖

    目录 java版源码 js版源码 在线绘制预览效果 关于计算的精确度 前些时间在更新我的坐标边界查询工具的时候,需要用到经纬度坐标点的距离计算,和以坐标点为中心生成一个指定距离为半径的圆,搜了一下没有 ...

  5. Electron桌面应用开发基础

    Electron桌面应用开发 Electron技术架构 地址:快速入门 | Electron Chromium 支持最新特性的浏览器 Node.js Javascript运行时,可实现文件读写 Nat ...

  6. Vue_Django 登录注册+图书管理系统

    Vue前端 注册页面 点击查看代码 <template> <div class="register"> <el-row :gutter="2 ...

  7. C#里的var和dynamic区别到底是什么,你真的搞懂了嘛

    前言 这个var和dynamic都是不确定的初始化类型,但是这两个本质上的不同.不同在哪儿呢?var编译阶段确定类型,dynamic运行时阶段确定类型.这种说法对不对呢?本篇看下 概括 以下详细叙述下 ...

  8. 【python基础】函数-模块

    函数的优点之一是,使用它们可将代码块与主程序分离.通过给函数指定函数名称,可让主程序容易理解的多.我们还可以更加细化,将函数存储在被称为模块的独立文件中,再将模块导入到主程序中.import关键字作用 ...

  9. 洛谷 P5065 不归之人与望眼欲穿的人们

    题意 一个长 \(n\) 的正整数序列 \(a\),支持单点修改数值,询问所有按位或值大于等于 \(k\) 的区间长度最短为多少. 数据范围:\(1\le n\le 50000, 0\le a_i, ...

  10. 使用 nuxt3 开发简约优雅的个人 blog

    起因 很早前我就有过搭建个人博客的想法,但是我希望使用纯前端实现,这样就不需要付出额外的后端维护成本,维护成本又低,而且更加安全.网上也有很多博客框架但是也不符合我的需求,所以我使用了nuxt3 + ...