Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x)spring 官方放弃了 Guava,而使用了性能更优秀的 Caffeine 作为默认缓存组件

一、引入依赖

 <dependency>
     <groupId>com.github.ben-manes.caffeine</groupId>
     <artifactId>caffeine</artifactId>
     <version>2.8.8</version>
 </dependency>
  • caffeine3.x版本不支持jdk1.8,所以这里选用2.8.8

二、自定义枚举

一个项目里可能需要缓存的数据有很多,比如用户信息,权限信息,菜单信息等等,我们需要给不同的场景分配不同的命名空间,并设置不同的过期时间

public enum CacheEnum {
    /**
     * 用户缓存,缓存时间单位/秒
     */
    CACHE_USERS("users", 2),
    /**
     * 菜单缓存,缓存时间单位/秒
     */
    CACHE_MENU("menu", 2),
    ;
    /**
     * 缓存名称
     */
    private final String name;
    /**
     * 过期时间
     */
    private final int expires;

}

三、缓存配置类

@Slf4j
public class CacheConfig {
   
    @Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        List<CaffeineCache> list = new ArrayList<>();
        //循环添加枚举类中自定义的缓存
        for (CacheEnum cacheEnum : CacheEnum.values()) {
            list.add(new CaffeineCache(cacheEnum.getName(),
                    Caffeine.newBuilder()
                            .initialCapacity(50)
                            .maximumSize(1000)
                             // 设置过期时间
                            .expireAfterWrite(cacheEnum.getExpires(), TimeUnit.SECONDS)
                            .build()));
        }
        cacheManager.setCaches(list);
        log.info("[cacheManager加载完成]");
        return cacheManager;
    }
}
  • initialCapacity=[integer]: 初始的缓存空间大小
  • maximumSize=[long]: 缓存的最大条数
  • maximumWeight=[long]: 缓存的最大权重
  • expireAfterAccess=[duration]: 最后一次写入或访问后经过固定时间过期
  • expireAfterWrite=[duration]: 最后一次写入后经过固定时间过期
  • refreshAfterWrite=[duration]: 创建缓存或者最近一次更新缓存后经过固定的时间间隔,刷新缓存
  • weakKeys: 打开key的弱引用
  • weakValues:打开value的弱引用
  • softValues:打开value的软引用
  • recordStats:开发统计功能

注意:

  • expireAfterWriteexpireAfterAccess同事存在时,以expireAfterWrite为准。
  • maximumSizemaximumWeight不可以同时使用
  • weakValuessoftValues不可以同时使用

如果是在自定义的starter里,还需要在MATE-INFO/spring.factories中配置EnableAutoConfiguration

四、工具类

public enum CacheUtil {
    
    /**
    * 工具类标记
    */
    X;
    
    private final CacheManager cm;

    CacheUtil() {
        cm = SpringUtil.getBean("cacheManager", CacheManager.class);
    }

    /**
     * 添加缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @param value     缓存值
     */
    public void put(String cacheName, String key, Object value) {
        Cache cache = cm.getCache(cacheName);
        cache.put(key, value);
    }

    /**
     * 获取缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     * @return
     */
    public <T> Optional<T> get(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache == null) {
           return Optional.empty();
        }
        Cache.ValueWrapper valueWrapper = cache.get(key);
        if (null == valueWrapper) {
            return Optional.empty();
        }
        return  Optional.of((T) valueWrapper.get());
    }

    /**
     * 失效缓存
     *
     * @param cacheName 缓存名称
     * @param key       缓存key
     */
    public void evict(String cacheName, String key) {
        Cache cache = cm.getCache(cacheName);
        if (cache != null) {
            cache.evict(key);
        }
    }
}
  • 工具类需要保证都是单例的,而枚举类天然支持单例,X表示工具类
  • 获取缓存使用Optional作为返回,是为了提醒使用者可能返回null的情况,需要做针对处理

五、单元测试

    @Test
    public void test_cache_put() throws InterruptedException {
        CacheUtil.X.put(CacheEnum.CACHE_USERS.getName(), "users", "zhangsan");
        CacheUtil.X.put(CacheEnum.CACHE_MENU.getName(), "menus", Arrays.asList("1", "2", "3", "4"));

        Optional<String> users = CacheUtil.X.get(CacheEnum.CACHE_USERS.getName(), "users");
        if (users.isPresent()) {
            String str = users.get();
            System.out.println(str);
        }
        Optional<List<String>> menus = CacheUtil.X.get(CacheEnum.CACHE_MENU.getName(), "menus");
        menus.ifPresent(System.out::println);

        // 测试缓存过期情况
        Thread.sleep(2000);
        Optional<String> users2 = CacheUtil.X.get(CacheEnum.CACHE_USERS.getName(), "users");
        if (users2.isPresent()) {
            String str = users2.get();
            System.out.println(str);
        }
        Optional<List<String>> menus2 = CacheUtil.X.get(CacheEnum.CACHE_MENU.getName(), "menus");
        menus2.ifPresent(System.out::println);
    }

最强本地缓存Caffeine的更多相关文章

  1. 解读JVM级别本地缓存Caffeine青出于蓝的要诀 —— 缘何会更强、如何去上手

    大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 在前面的几篇文章中,我们一起聊了下本地 ...

  2. 解读JVM级别本地缓存Caffeine青出于蓝的要诀3 —— 讲透Caffeine的数据驱逐淘汰机制与用法

    大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 上一篇文章中,我们聊了下Caffein ...

  3. 本地缓存Caffeine

    Caffeine 说起Guava Cache,很多人都不会陌生,它是Google Guava工具包中的一个非常方便易用的本地化缓存实现,基于LRU算法实现,支持多种缓存过期策略.由于Guava的大量使 ...

  4. 解读JVM级别本地缓存Caffeine青出于蓝的要诀2 —— 弄清楚Caffeine的同步、异步回源方式

    大家好,又见面了. 本文是笔者作为掘金技术社区签约作者的身份输出的缓存专栏系列内容,将会通过系列专题,讲清楚缓存的方方面面.如果感兴趣,欢迎关注以获取后续更新. 上一篇文章中,我们继Guava Cac ...

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

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

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

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

  7. 本地缓存解决方案-Caffeine Cache

    1.1 关于Caffeine Cache ​ Google Guava Cache是一种非常优秀本地缓存解决方案,提供了基于容量,时间和引用的缓存回收方式.基于容量的方式内部实现采用LRU算法,基于引 ...

  8. spring boot: 用redis的消息订阅功能更新应用内的caffeine本地缓存(spring boot 2.3.2)

    一,为什么要更新caffeine缓存? 1,caffeine缓存的优点和缺点 生产环境中,caffeine缓存是我们在应用中使用的本地缓存, 它的优势在于存在于应用内,访问速度最快,通常都不到1ms就 ...

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

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

  10. Java高性能本地缓存框架Caffeine

    一.序言 Caffeine是一个进程内部缓存框架,使用了Java 8最新的[StampedLock]乐观锁技术,极大提高缓存并发吞吐量,一个高性能的 Java 缓存库,被称为最快缓存. 二.缓存简介 ...

随机推荐

  1. iOS 屏幕旋转的设置方法

    VC上屏幕旋转的方式有2种 1.因重力导致的屏幕旋转 条件:shouldAutorotate返回true,设备开启了屏幕旋转开关. 设备发生重力旋转. 2.单页面强制旋转 条件:无. 设置设备旋转方向 ...

  2. PCIe诞生20年来最大变革!引入光学传输

    PCI-SIG组织官方宣布,已经成立新的光学工作组(Optical Workgroup),研究为PCIe规范引入光学传输接口的可能性. PCIe标准是Intel 2001年提出的,2003年发布1.0 ...

  3. MySQL主主同步环境出现1236错误

    环境: MySQL 5.7.25 主主架构 故障现象: 发现互相之间的同步均发生异常,两端均出现1236错误,在两个主节点上分别执行show slave status显示的关键信息如下: Master ...

  4. delphi的bpl、dcp 、dcu

    BPL  英文全称 Borland Package library ,是一种特殊的DLL文件,用于代码重用和减少可执行文件.编译bpl时,仅需要添加相应功能的pas文件,如果有窗体,则需要添加dfm文 ...

  5. 【译】介绍 MSTest Runner – CLI、Visual Studio 等

    原文 | Amaury Levé, Marco Rossignoli, Jakub Jareš 翻译 | 郑子铭 我们很高兴推出 MSTest runner,这是一个用于 MSTest 测试的新型轻量 ...

  6. 开源.NetCore通用工具库Xmtool使用连载 - 发送邮件篇

    [Github源码] <上一篇> 介绍了Xmtool工具库中的随机值类库,今天我们继续为大家介绍其中的邮件发送类库. 发送邮件是系统开发中经常需要的功能,广泛应用于消息通知.异常告警.内容 ...

  7. 【OpenGL ES】绘制立方体

    1 前言 ​ 本文主要介绍使用 OpenGL ES 绘制立方体,读者如果对 OpenGL ES 不太熟悉,请回顾以下内容: 绘制三角形 绘制彩色三角形 绘制正方形 绘制圆形 ​ 在绘制立方体的过程中, ...

  8. Laravel入坑指南(4)——数据库(Mysql)

    来来来,新的一节出炉了.这一节大家一起了解,Laravel如何对Mysql进行CURD. 我们回顾一下,PHP操作Mysql无非就是通过五个要素:host(地址).username(用户名).pass ...

  9. Vue+SpringBoot+ElementUI实战学生管理系统-6.院系管理模块

    1.章节介绍 前一篇介绍了用户管理模块,这一篇编写院系管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 院系列表 修改院系 4.模块 ...

  10. Spring Boot图书管理系统项目实战-1.系统功能和架构介绍

    导航: next:2.项目搭建 1.项目源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.项目背景 自己闲着没事写的,供初学spring boot和在校大学生毕业设计学习交流.大神请忽略:) ...