聊聊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
繁體地址,請注明出處:http://hk.pswp.cn/web/80364.shtml
英文地址,請注明出處:http://en.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;難以滿足現代工業生…