聊聊JetCache的缓存构建

本文主要研究一下JetCache的缓存构建

invokeWithCached

com/alicp/jetcache/anno/method/CacheHandler.java

    private static Object invokeWithCached(CacheInvokeContext context)throws Throwable {CacheInvokeConfig cic = context.getCacheInvokeConfig();CachedAnnoConfig cac = cic.getCachedAnnoConfig();Cache cache = context.getCacheFunction().apply(context, cac);if (cache == null) {logger.error("no cache with name: " + context.getMethod());return invokeOrigin(context);}Object key = ExpressionUtil.evalKey(context, cic.getCachedAnnoConfig());if (key == null) {return loadAndCount(context, cache, key);}if (!ExpressionUtil.evalCondition(context, cic.getCachedAnnoConfig())) {return loadAndCount(context, cache, key);}try {CacheLoader loader = new CacheLoader() {@Overridepublic Object load(Object k) throws Throwable {Object result = invokeOrigin(context);context.setResult(result);return result;}@Overridepublic boolean vetoCacheUpdate() {return !ExpressionUtil.evalPostCondition(context, cic.getCachedAnnoConfig());}};Object result = cache.computeIfAbsent(key, loader);return result;} catch (CacheInvokeException e) {throw e.getCause();}}

invokeWithCached先通过context.getCacheFunction().apply(context, cac)去获取缓存

setCacheFunction

com/alicp/jetcache/anno/support/CacheContext.java

    public CacheInvokeContext createCacheInvokeContext(ConfigMap configMap) {CacheInvokeContext c = newCacheInvokeContext();c.setCacheFunction((invokeContext, cacheAnnoConfig) -> {Cache cache = cacheAnnoConfig.getCache();if (cache == null) {if (cacheAnnoConfig instanceof CachedAnnoConfig) {cache = createCacheByCachedConfig((CachedAnnoConfig) cacheAnnoConfig, invokeContext);} else if ((cacheAnnoConfig instanceof CacheInvalidateAnnoConfig) || (cacheAnnoConfig instanceof CacheUpdateAnnoConfig)) {CacheInvokeConfig cacheDefineConfig = configMap.getByCacheName(cacheAnnoConfig.getArea(), cacheAnnoConfig.getName());if (cacheDefineConfig == null) {String message = "can't find @Cached definition with area=" + cacheAnnoConfig.getArea()+ " name=" + cacheAnnoConfig.getName() +", specified in " + cacheAnnoConfig.getDefineMethod();CacheConfigException e = new CacheConfigException(message);logger.error("Cache operation aborted because can't find @Cached definition", e);return null;}cache = createCacheByCachedConfig(cacheDefineConfig.getCachedAnnoConfig(), invokeContext);}cacheAnnoConfig.setCache(cache);}return cache;});return c;}

createCacheInvokeContext设置了cacheFunction,使用了双重检锁去构建cache,对于CachedAnnoConfig是走了createCacheByCachedConfig

createCacheByCachedConfig

com/alicp/jetcache/anno/support/CacheContext.java

    private Cache createCacheByCachedConfig(CachedAnnoConfig ac, CacheInvokeContext invokeContext) {String area = ac.getArea();String cacheName = ac.getName();if (CacheConsts.isUndefined(cacheName)) {cacheName = configProvider.createCacheNameGenerator(invokeContext.getHiddenPackages()).generateCacheName(invokeContext.getMethod(), invokeContext.getTargetObject());}Cache cache = __createOrGetCache(ac, area, cacheName);return cache;}public Cache __createOrGetCache(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {String fullCacheName = area + "_" + cacheName;Cache cache = cacheManager.getCacheWithoutCreate(area, cacheName);if (cache == null) {synchronized (this) {cache = cacheManager.getCacheWithoutCreate(area, cacheName);if (cache == null) {if (globalCacheConfig.isAreaInCacheName()) {// for compatible reason, if we use default configuration, the prefix should same to that version <=2.4.3cache = buildCache(cachedAnnoConfig, area, fullCacheName);} else {cache = buildCache(cachedAnnoConfig, area, cacheName);}cacheManager.putCache(area, cacheName, cache);}}}return cache;}    

__createOrGetCache再次使用双重检锁通过buildCache去构建Cache,默认globalCacheConfig.isAreaInCacheName()为false,构建完放入cacheManager

buildCache

com/alicp/jetcache/anno/support/CacheContext.java

    protected Cache buildCache(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {Cache cache;if (cachedAnnoConfig.getCacheType() == CacheType.LOCAL) {cache = buildLocal(cachedAnnoConfig, area);} else if (cachedAnnoConfig.getCacheType() == CacheType.REMOTE) {cache = buildRemote(cachedAnnoConfig, area, cacheName);} else {Cache local = buildLocal(cachedAnnoConfig, area);Cache remote = buildRemote(cachedAnnoConfig, area, cacheName);boolean useExpireOfSubCache = cachedAnnoConfig.getLocalExpire() > 0;cache = MultiLevelCacheBuilder.createMultiLevelCacheBuilder().expireAfterWrite(remote.config().getExpireAfterWriteInMillis(), TimeUnit.MILLISECONDS).addCache(local, remote).useExpireOfSubCache(useExpireOfSubCache).cacheNullValue(cachedAnnoConfig.isCacheNullValue()).buildCache();}cache.config().setRefreshPolicy(cachedAnnoConfig.getRefreshPolicy());cache = new CacheHandler.CacheHandlerRefreshCache(cache);cache.config().setCachePenetrationProtect(globalCacheConfig.isPenetrationProtect());PenetrationProtectConfig protectConfig = cachedAnnoConfig.getPenetrationProtectConfig();if (protectConfig != null) {cache.config().setCachePenetrationProtect(protectConfig.isPenetrationProtect());cache.config().setPenetrationProtectTimeout(protectConfig.getPenetrationProtectTimeout());}if (configProvider.getCacheMonitorManager() != null) {configProvider.getCacheMonitorManager().addMonitors(area, cacheName, cache);}return cache;}

buildCache根据CacheType去构建,对于REMOTE是执行buildRemote

buildRemote

    protected Cache buildRemote(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {ExternalCacheBuilder cacheBuilder = (ExternalCacheBuilder) globalCacheConfig.getRemoteCacheBuilders().get(area);if (cacheBuilder == null) {throw new CacheConfigException("no remote cache builder: " + area);}cacheBuilder = (ExternalCacheBuilder) cacheBuilder.clone();if (cachedAnnoConfig.getExpire() > 0 ) {cacheBuilder.expireAfterWrite(cachedAnnoConfig.getExpire(), cachedAnnoConfig.getTimeUnit());}if (cacheBuilder.getConfig().getKeyPrefix() != null) {cacheBuilder.setKeyPrefix(cacheBuilder.getConfig().getKeyPrefix() + cacheName);} else {cacheBuilder.setKeyPrefix(cacheName);}if (!CacheConsts.isUndefined(cachedAnnoConfig.getKeyConvertor())) {cacheBuilder.setKeyConvertor(configProvider.parseKeyConvertor(cachedAnnoConfig.getKeyConvertor()));}if (!CacheConsts.isUndefined(cachedAnnoConfig.getSerialPolicy())) {cacheBuilder.setValueEncoder(configProvider.parseValueEncoder(cachedAnnoConfig.getSerialPolicy()));cacheBuilder.setValueDecoder(configProvider.parseValueDecoder(cachedAnnoConfig.getSerialPolicy()));}cacheBuilder.setCacheNullValue(cachedAnnoConfig.isCacheNullValue());return cacheBuilder.buildCache();}

这里获取remote的cacheBuilder,进行clone,然后根据cachedAnnoConfig进行属性覆盖,然后执行cacheBuilder.buildCache()构建;这里keyPrefix默认为null,所以这里的keyPrefix为不带aera的cacheName;ExternalCacheBuilder有MockRemoteCacheBuilder、RedisLettuceCacheBuilder两个子类。

小结

JetCache延迟构建Cache,通过CacheContext.buildCache根据cacheType进行构建。

doc

  • Builder

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

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

相关文章

c#队列及其操作

可以用数组、链表实现队列&#xff0c;大致与栈相似&#xff0c;简要介绍下队列实现吧。值得注意的是循环队列判空判满操作&#xff0c;在用链表实现时需要额外思考下出入队列条件。 设计头文件 #ifndef ARRAY_QUEUE_H #define ARRAY_QUEUE_H#include <stdbool.h> #incl…

开源项目实战学习之YOLO11:12.3 ultralytics-models-sam-encoders.py源码分析

👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-encoders.pyblocks.py: 定义模型中的各…

STM32 | FreeRTOS 消息队列

01 一、概述 队列又称消息队列&#xff0c;是一种常用于任务间通信的数据结构&#xff0c;队列可以在任务与任务间、中断和任务间传递信息&#xff0c;实现了任务接收来自其他任务或中断的不固定长度的消息&#xff0c;任务能够从队列里面读取消息&#xff0c;当队列中的消…

Java 安全漏洞扫描工具:如何快速发现和修复潜在问题?

Java 安全漏洞扫描工具&#xff1a;如何快速发现和修复潜在问题&#xff1f; 在当今的软件开发领域&#xff0c;Java 作为一种广泛使用的编程语言&#xff0c;其应用的规模和复杂度不断攀升。然而&#xff0c;随着应用的拓展&#xff0c;Java 应用面临的潜在安全漏洞风险也日益…

Python绘制克利夫兰点图:从入门到实战

Python绘制克利夫兰点图&#xff1a;从入门到实战 引言 克利夫兰点图&#xff08;Cleveland Dot Plot&#xff09;是一种强大的数据可视化工具&#xff0c;由统计学家William Cleveland在1984年提出。这种图表特别适合展示多个类别的数值比较&#xff0c;比传统的条形图更直观…

LVGL- Calendar 日历控件

1 日历控件 1.1 日历背景 lv_calendar 是 LVGL&#xff08;Light and Versatile Graphics Library&#xff09;提供的标准 GUI 控件之一&#xff0c;用于显示日历视图。它支持用户查看某年某月的完整日历&#xff0c;还可以实现点击日期、标记日期、导航月份等操作。这个控件…

多指标组合策略

该策略(MultiConditionStrategy)是一种基于多种技术指标和市场条件的交易策略。它通过综合考虑多个条件来生成交易信号,从而决定买入或卖出的时机。 以下是对该策略的详细分析: 交易逻辑思路 1. 条件1:星期几和价格变化判断 - 该条件根据当前日期是星期几以及价格的变化…

BC 范式与 4NF

接下来我们详细解释 BC 范式&#xff08;Boyce-Codd范式&#xff0c;简称 BCNF&#xff09;&#xff0c;并通过具体例子说明其定义和应用。 一、BC范式的定义 BC范式&#xff08;Boyce-Codd范式&#xff0c;BCNF&#xff09;是数据库规范化理论中的一种范式&#xff0c;它比第…

基于 CSS Grid 的网页,拆解页面整体布局结构

通过以下示例拆解网页整体布局结构&#xff1a; 一、基础结构&#xff08;HTML骨架&#xff09; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"…

采购流程规范化如何实现?日事清流程自动化助力需求、采购、财务高效协作

采购审批流程全靠人推进&#xff0c;内耗严重&#xff0c;效率低下&#xff1f; 花重金上了OA&#xff0c;结果功能有局限、不灵活&#xff1f; 问题出在哪里&#xff1f;是我们的要求太多、太苛刻吗&#xff1f;NO&#xff01; 流程名称&#xff1a; 采购审批管理 流程功能…

全栈项目搭建指南:Nuxt.js + Node.js + MongoDB

全栈项目搭建指南&#xff1a;Nuxt.js Node.js MongoDB 一、项目概述 我们将构建一个完整的全栈应用&#xff0c;包含&#xff1a; 前端&#xff1a;Nuxt.js (SSR渲染)后端&#xff1a;Node.js (Express/Koa框架)数据库&#xff1a;MongoDB后台管理系统&#xff1a;集成在同…

NVMe简介6之PCIe事务层

PCIe的事务层连接了PCIe设备核心与PCIe链路&#xff0c;这里主要基于PCIe事务层进行分析。事务层采用TLP传输事务&#xff0c;完整的TLP由TLPPrefix、TLP头、Payload和TLP Digest组成。TLP头是TLP中最关键的部分&#xff0c;一般由三个或四个双字的长度&#xff0c;其格式定义如…

Python异常模块和包

异常 当检测到一个错误时&#xff0c;Python解释器就无法继续执行了&#xff0c;反而出现了一些错误的提示&#xff0c;这就是所谓的“异常”, 也就是我们常说的BUG 例如&#xff1a;以r方式打开一个不存在的文件。 f open(‘python1.txt’,‘r’,encoding‘utf-8’) 当我们…

汇编:循环程序设计

一、 实验要求 熟练掌握循环程序设计的基本方法熟练掌握单片机外部存储空间的访问方法 二、 实验设计 1.整体思路 先初始化一些寄存器和数据存储位置&#xff0c;然后调用两个子程序Procedure1和Procedure2&#xff0c;分别从SRC复制数据到DEST&#xff0c;一个从开头到末尾&…

典籍知识问答模块AI问答bug修改

一、修改流式数据处理问题 1.问题描述&#xff1a;由于传来的数据形式如下&#xff1a; event:START data:350 data:< data:t data:h data:i data:n data:k data:> data: data: data: data: data:嗯 data:&#xff0c; 导致需要修改获取正常的当前信息id并更…

【金仓数据库征文】- 金融HTAP实战:KingbaseES实时风控与毫秒级分析一体化架构

文章目录 引言&#xff1a;金融数字化转型的HTAP引擎革命一、HTAP架构设计与资源隔离策略1.1 混合负载物理隔离架构1.1.1 行列存储分区策略1.1.2 四级资源隔离机制 二、实时流处理与增量同步优化2.1 分钟级新鲜度保障2.1.1 WAL日志增量同步2.1.2 流计算优化 2.2 物化视图实时刷…

季报中的FPGA行业:U型反转,春江水暖

上周Lattice,AMD两大厂商相继发布2025 Q1季报,尽管恢复速度各异,但同时传递出FPGA行业整体回暖的复苏信号。 5月5日,Lattice交出了“勉强及格”的答卷,报告季度营收1亿2000万,与华尔街的预期基本相符。 对于这家聚焦在中小规模器件的领先厂商而言,按照其CEO的预期,长…

使用 javap 深入理解 Java 字节码

引言 Java 是一种广泛使用的高级编程语言,其独特之处在于编译后的代码不是直接的机器码,而是一种称为字节码的中间表示形式。字节码存储在 .class 文件中,由 Java 虚拟机 (JVM) 解释或即时编译为特定平台的机器码。这种设计赋予了 Java 平台无关性,即“一次编写,到处运行…

LeetCode_sql刷题(3482.分析组织层级)

题目描述&#xff1a;3482. 分析组织层级 - 力扣&#xff08;LeetCode&#xff09; 表&#xff1a;Employees ------------------------- | Column Name | Type | ------------------------- | employee_id | int | | employee_name | varchar | | manager_id …

工业场景轮式巡检机器人纯视觉识别导航的优势剖析与前景展望

一、引言 1.1 研究背景与意义 在工业 4.0 的大背景下&#xff0c;工业生产的智能化、自动化水平不断提高&#xff0c;对工业场景的巡检工作提出了更高的要求。传统的人工巡检方式不仅效率低下、成本高昂&#xff0c;而且容易受到人为因素的影响&#xff0c;难以满足现代工业生…