【springboot整合】Spring缓存抽象

news2024/9/22 7:33:17

JSR-107简介

为了统一缓存开发规范,以及提升缓存开发的扩展性,J2EE发布了JSR-107缓存开发规范。

Java Caching定义了5个核心接口,分别是CachingProvider、CacheManger、Cache、Entry和Expiry

  • CachingProvider:定义了创建、配置、获取、管理和控制多个CacheManger。一个应用可以再运行期间访问多个CachingProvider
  • CacheManger:定义了创建、配置、获取、管理和控制多个唯一命名Cache,这些Cache存在于CacheManger的上下文中
  • Cache:是一个类似Map的数据结构并临时存储以Key为索引的值
  • Entry:key-value键值对
  • Expiry:每一个存储在Cache中的条目有一个定义的有效期。一旦超过这个时间,条目为过期状态。过期状态的条目不可访问、更新和删除。可通过该ExpiryPolicy设置

大概可以用这样的数据结构表示:

Map<CachingProviderName,Map<CacheMangerName,Map<CacheName,Map<k,v>>

Spring缓存抽象

Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManger接口来统一不同的缓存技术;并支持使用Cache(JSR-107)注解简化开发

  • Cache接口为换出的组件规范定义,包含缓存的各种操作集合
  • Cache接口下Spring提供了个xxxCache的实现;如RedisCache、EhCacheCache、ConcurrentMapCache等;

缓存注解

image.png

缓存SpEL表达式

image.png

缓存工作原理

  1. 自动配置类:CacheAutoConfiguration 他的作用主要是通过Import注解引入各个缓存配置类
    • org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration
    • org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration
  2. 然后按顺序根据配置类上的Conditional条件判断,是哪个配置类生效,默认生效为SimpleCacheConfiguration配置类
  3. SimpleCacheConfiguration只做了一件事,那就是向容器中注入了一个ConcurrentMapCacheManager

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {

    @Bean
    ConcurrentMapCacheManager cacheManager(CacheProperties cacheProperties,
                                           CacheManagerCustomizers cacheManagerCustomizers) {
        ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
        List<String> cacheNames = cacheProperties.getCacheNames();
        if (!cacheNames.isEmpty()) {
            cacheManager.setCacheNames(cacheNames);
        }
        return cacheManagerCustomizers.customize(cacheManager);
    }

}
  1. 通过ConcurrentMapCacheManager获取和创建ConcurrentMapCache缓存组件。使用ConcurrentMap进行管理缓存组件,可以看出实现的数据结构其实就是ConcurrentHashMap
public class ConcurrentMapCacheManager {

    private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap<>(16);

    /**
     * 通过name获取缓存组件,如果没有就创建一个
     */
    @Override
    @Nullable
    public Cache getCache(String name) {
        Cache cache = this.cacheMap.get(name);
        if (cache == null && this.dynamic) {
            synchronized (this.cacheMap) {
                cache = this.cacheMap.get(name);
                if (cache == null) {
                    // 获取缓存组件为空时进行创建
                    cache = createConcurrentMapCache(name);
                    this.cacheMap.put(name, cache);
                }
            }
        }
        return cache;
    }

    /**
     * 创建一个ConcurrentMapCache缓存组件
     */
    protected Cache createConcurrentMapCache(String name) {
        SerializationDelegate actualSerialization = (isStoreByValue() ? this.serialization : null);
        return new ConcurrentMapCache(name, new ConcurrentHashMap<>(256),
                isAllowNullValues(), actualSerialization);

    }
}
  1. ConcurrentMapCache将数据保存在ConcurrentMap中,也是使用ConcurrentHashMap进行缓存数据的操作
public class ConcurrentMapCache extends AbstractValueAdaptingCache {
    // 组件的名称
    private final String name;
    // 数据存放在这里
    private final ConcurrentMap<Object, Object> store;

    // 使用ConcurrentHashMap进行数据操作
    public ConcurrentMapCache(String name) {
        this(name, new ConcurrentHashMap<>(256), true);
    }

    /**
     * 查询缓存
     */
    @Override
    @Nullable
    protected Object lookup(Object key) {
        return this.store.get(key);
    }

    @Override
    @Nullable
    public <T> T get(Object key, Callable<T> valueLoader) {
        return (T) fromStoreValue(this.store.computeIfAbsent(key, k -> {
            try {
                return toStoreValue(valueLoader.call());
            } catch (Throwable ex) {
                throw new ValueRetrievalException(key, valueLoader, ex);
            }
        }));
    }

    // 存放缓存数据,实际就是map.put(key,value)
    @Override
    public void put(Object key, @Nullable Object value) {
        this.store.put(key, toStoreValue(value));
    }
}

运行流程

@Cacheable:

  1. 方法运行前,按照cacheNames查询缓存组件,第一次获取如果没有会自动创建缓存组件;
  2. 去Cache中查找缓存的内容,使用一个key,默认为方法的参数;key是通过keyGenerator生成的,SimpleCacheConfiguration默认使用SimpleKeyGenerator生成
public class SimpleKeyGenerator implements KeyGenerator {

    public static Object generateKey(Object... params) {
        if (params.length == 0) {
            return SimpleKey.EMPTY;
        }
        if (params.length == 1) {
            Object param = params[0];
            if (param != null && !param.getClass().isArray()) {
                return param;
            }
        }
        return new SimpleKey(params);
    }
}
  1. 没有查询到缓存就调用目标方法
  2. 将目标方法返回的结果,放进缓存中
public class ConcurrentMapCache extends AbstractValueAdaptingCache {

    @Override
    public void put(Object key, @Nullable Object value) {
        this.store.put(key, toStoreValue(value));
    }
}

Gitee源码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/673728.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Java毕业论文管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

Redis【入门篇】---- Redis常见命令

Redis【入门篇】---- Redis常见命令 1. Redis数据结构介绍2. Redis 通用命令3. Redis命令-String命令4. Redis命令-Key的层级结构5. Redis命令-Hash命令6. Redis命令-List命令7. Redis命令-Set命令8. Redis命令-SortedSet类型 1. Redis数据结构介绍 Redis是一个key-value的数据…

调查问卷Type Form的集成

简介 Typeform是一家制作线上调查问卷的公司。 Muoz 和 David Okuniev两人于2012年创作出一个更加动态、更具交互性的用户调查工具&#xff0c;每次只提一个问题&#xff0c;并且根据用户的回答为其呈现下一个问题&#xff0c;像和朋友间的对话一样&#xff0c;让用户在不知不…

边缘计算开源平台

边缘计算 文章目录 边缘计算前言01 边缘计算开源平台概述02 面向物联网端的边缘计算开源平台2.1 EdgeXFoundry2.2 ApacheEdgent 03 面向边缘云的边缘计算开源平台3.1 CORD3.2 Akraino EdgeStack 04 面向云边融合的边缘计算开源平台05 构建边缘计算平台的开源软件06 结束语 前言…

类皮肤全属性凝胶电子皮肤

目前电子皮肤相关工作仅①提升单一或几个刺激感知属性&#xff08;压力、温度等&#xff09;&#xff1b;②研究部分理化属性和感知属性的结合。但这些工作仅覆盖皮肤的两种或三种属性&#xff0c;距离实现皮肤般丰富的刺激感知感官和理化特性还有很大差距。而覆盖人类皮肤的所…

linux-virtualbox安装centOS7.9

一、windows10安装virtualbox 安装包->右键->以管理员身份运行->下一步 ->选择安装位置->下一步 ->是&#xff08;网络中断&#xff1f;&#xff09; ->是&#xff08;安装一些辅助工具包&#xff09; ->安装 ->完成 二、virtualbox新建centOS7.9虚…

【Python 基础篇】Python 文件操作

文章目录 导言一、文件操作的作用二、文件的基本操作1、打开文件2、读写文件① 读取文件② 写入文件 3、关闭文件 三、文件备份四、文件和文件夹的操作结语 导言 在编程领域中&#xff0c;文件操作是一项基础且常见的任务。无论是读取配置文件、处理数据文件&#xff0c;还是备…

MySQL保姆安装教程

文章目录 前言一、MySQL官网二、离线安装包步骤三、环境配置四、验证安装是否成功在这里插入图片描述 五、可视化工具连接总结 前言 对于第一次安装mysql是有点难度&#xff0c;现在我会把安装流程搞出来。 一、MySQL官网 MySQL Installer 8.0.33安装&#xff08;不想安装这个…

Windows下redis的安装与使用

一、下载 redis.io 官网没有Windows版本的&#xff0c;需要去redis-windows下载。 二、使用与配置 2.1 解压安装 redis的Windows版本&#xff0c;有.msi和.zip两种格式。这里使用更为方便&#xff0c;直接解压就可以使用的.zip格式。 将Redis-x64-5.0.14.1.zip解压至D盘的…

【Java-SpringBoot+Vue+MySql】Day3.3-MybatisPlus说明与使用

目录 一、MybatisPlus快速入门 1、知识轰炸 2、实操演练 &#xff08;1&#xff09;新建项目 &#xff08;2&#xff09;添加依赖 &#xff08;3&#xff09;添加配置 &#xff08;4&#xff09;添加映射层 &#xff08;5&#xff09;启动类中添加注解 &#xff08;6&a…

【通过Data Studio连接openGauss】---快速入门

【通过Data Studio连接openGauss】---快速入门 &#x1f53b; 一、访问openGauss&#x1f530; 1.1 确认连接信息&#xff08;单节点&#xff09;&#x1f530; 1.2 使用gsql访问openGauss&#xff08;本地连接数据库&#xff09;&#x1f530; 1.3 使用gsql访问openGauss&…

玩机搞机------安卓手机分区操作中的的各种工具 提取分区 备份分区 檫除分区 推荐一

喜欢玩机搞机的朋友们经常对手机系统进行安装玩机操作。但有时候指令类输入和操作步骤比较繁琐。耽误时间。有些工具就比较方便操作。陆续会整理一些玩机搞机中的简单工具给爱好者使用。本期整理一些关于手机分区的工具推荐 &#x1f494;&#x1f494;&#x1f494; AB AVB分…

Android的详细介绍

目录&#xff1a; Android诞生 Android系统架构 Android系统版本 Android应用开发特色 Android诞生 2003年10月&#xff0c;Andy Rubin等人创建了Android公司&#xff0c;并组建了Android团队。 2005年8月17日&#xff0c;Google低调收购了成立仅22个月的高科技企…

【新星计划·2023】Linux目录结构

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 前言 本文将讲解Linux目录结构与功能&#xff0c;以及目录解释&#xff0c;最近这段时间会持续更新关于Linux的基础知识&#xff0c;期待你的…

机器视觉初步6-1:基于梯度的图像分割

把基于梯度的图像分割单独拿出来。 文章目录 一、图像梯度相关算子的原理1. Sobel算子2. Prewitt算子3. Roberts算子 二、python和halcon算子实现1.python实现2.halcon实现 基于梯度的图像分割方法利用像素之间的梯度信息来进行图像分割。 梯度 1是图像中像素灰度值变化最快的…

macOS Monterey 12.6.7 (21G651) 正式版发布,ISO、IPSW、PKG 下载

macOS Monterey 12.6.7 (21G651) 正式版发布&#xff0c;ISO、IPSW、PKG 下载 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持…

macOS Big Sur 11.7.8 (20G1351) 正式版 ISO、PKG、DMG、IPSW 下载

macOS Big Sur 11.7.8 (20G1351) 正式版 ISO、PKG、DMG、IPSW 下载 本站下载的 macOS 软件包&#xff0c;既可以拖拽到 Applications&#xff08;应用程序&#xff09;下直接安装&#xff0c;也可以制作启动 U 盘安装&#xff0c;或者在虚拟机中启动安装。另外也支持在 Window…

Windows 10 |VMware开启虚拟化的最全面说明

前言&#xff1a; Windows作为工作机&#xff0c;对于计算机系的同学来说&#xff0c;主要是在于利用图形化的界面直观的创建虚拟机&#xff08;典型的有代表性的是virtualbox和VMware这两家公司的桌面级虚拟化软件&#xff09;&#xff0c;尤其是小白这样的初学者&#xff0c…

吴恩达ChatGPT《Prompt Engineering》笔记

ChatGPT 提示词工程师教程 1. 课程介绍 1.1 ChatGPT 相关术语 LLM&#xff1a;Large Language Model&#xff0c;大语言模型 Instruction Tuned LLM&#xff1a;经过指令微调的大语言模型 Prompt&#xff1a;提示词 RLHF&#xff1a;Reinforcement Learning from Human F…

英特尔oneAPI人工智能黑客松 - 机器视觉挑战案例

写在前面&#xff1a;博主是一只经过实战开发历练后投身培训事业的“小山猪”&#xff0c;昵称取自动画片《狮子王》中的“彭彭”&#xff0c;总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域&#xff0c;如今终有小成…