最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot?集成Caffeine實現(xiàn)一級緩存及常遇到場景

 更新時間:2025年06月25日 10:28:46   作者:寅燈  
文章講解了SpringBoot集成Caffeine實現(xiàn)一級緩存的方法,包括配置依賴、設(shè)置多緩存超時、業(yè)務(wù)與控制層調(diào)用方式,以及注解獲取數(shù)據(jù),重點指出自調(diào)用導(dǎo)致注解失效問題,并提供拆分Service的解決方案,強調(diào)Caffeine性能優(yōu)于GuavaCache,感興趣的朋友跟隨小編一起看看吧

SpeingBoot 集成Caffeine實現(xiàn)一級緩存使我們經(jīng)常遇到的場景。今天我們具體分享一下:

首先 Caffeine 作為一級緩存,它是 Spring 5.x 默認(rèn)的本地緩存實現(xiàn),性能優(yōu)于 Guava Cache,且支持過期時間設(shè)置。緩存執(zhí)行的流程圖如下:

1、pom文件引入包

         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.9.3</version> <!-- 兼容 Spring Boot 2.3.5 的版本 -->
        </dependency>
       

2、換成配置類

import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.TimeUnit;
@Configuration
@EnableCaching  
public class CacheConfig {
   /**
    Caffeine 配置參數(shù):
    expireAfterWrite:寫入后多久過期
    expireAfterAccess:最后訪問后多久過期
    maximumSize:緩存的最大元素數(shù)量
    weakKeys/weakValues:使用弱引用,支持垃圾回收
    **/
    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .expireAfterWrite(1, TimeUnit.MINUTES)//可以選多種時間
                .maximumSize(10));//最大緩存?zhèn)€數(shù)
        // 配置特定緩存(超時時間5分鐘,到時間自動置為null)
        cacheManager.setCacheNames(java.util.Arrays.asList("timeoutParam"));
        return cacheManager;
    }
}

1)配置多個緩存

@Bean
    public CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        // 配置不同的緩存區(qū)域(可根據(jù)業(yè)務(wù)需求設(shè)置不同的超時時間)
        cacheManager.setCaches(Arrays.asList(
                new CaffeineCache("timeoutParams",
                        Caffeine.newBuilder()
                                .expireAfterWrite(5, TimeUnit.MINUTES) // 5分鐘過期
                                .maximumSize(100)
                                .build()
                ),
                new CaffeineCache("longTermCache",
                        Caffeine.newBuilder()
                                .expireAfterWrite(1, TimeUnit.HOURS) // 1小時過期
                                .maximumSize(1000)
                                .build()
                )
        ));
        return cacheManager;
    }

不同緩存數(shù)據(jù)的超時時間可能不一樣,因此需要設(shè)置不同的緩存。 

3、業(yè)務(wù)層實現(xiàn)

import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;
@Service
public class MyService {
    // 獲取參數(shù)(從緩存讀取,若無則執(zhí)行方法并緩存結(jié)果)unless:條件表達(dá)式,滿足條件則不緩存(如 #result == null)
    @Cacheable(value = "timeoutParams", key = "#paramName")
    public String getParam(String paramName) {
        // 模擬從數(shù)據(jù)庫或其他數(shù)據(jù)源獲取
        System.out.println("從數(shù)據(jù)源加載參數(shù): " + paramName);
        return loadParamFromDB(paramName);
    }
    // 更新參數(shù)(強制刷新緩存,即使緩存存在)
    @CachePut(value = "timeoutParams", key = "#paramName")
    public String updateParam(String paramName, String newValue) {
        // 保存到數(shù)據(jù)庫
        saveParamToDB(paramName, newValue);
        return newValue;
    }
    // 清除緩存:調(diào)用此方法后,指定緩存鍵將被刪除
    @CacheEvict(value = "timeoutParams", key = "#paramName")
    public void clearParam(String paramName) {
        System.out.println("清除緩存: " + paramName);
        // 通常無需方法體,僅用于觸發(fā)緩存清除
    }
    // 模擬數(shù)據(jù)庫操作
    private String loadParamFromDB(String paramName) {
        // 實際項目中從數(shù)據(jù)庫或其他數(shù)據(jù)源獲取
        return "默認(rèn)值";
    }
    private void saveParamToDB(String paramName, String value) {
        // 實際項目中保存到數(shù)據(jù)庫
    }
}

 4、控制層調(diào)用

       // 第一次調(diào)用,會從數(shù)據(jù)源加載
        String value1 = myService.getParam("testParam");
        System.out.println("第一次獲取: " + value1);
        // 第二次調(diào)用,會從緩存獲取
        String value2 = myService.getParam("testParam");
        System.out.println("第二次獲取: " + value2);

5、通過key獲取數(shù)據(jù)

1)通過key手動插入

@Service
public class ManualCacheService {
    @Autowired
    private CacheManager cacheManager;
    public void initCacheManually(String key, Object value) {
        Cache cache = cacheManager.getCache("paramCache");
        if (cache != null) {
            cache.put(key, value);  // 手動放入緩存
            System.out.println("手動初始化緩存: " + key + " = " + value);
        }
    }
}

2)手動獲取

@Service
public class CacheAccessService {
    @Autowired
    private CacheManager cacheManager;
    public Object getValueManually(String key) {
        Cache cache = cacheManager.getCache("paramCache");
        if (cache != null) {
            Cache.ValueWrapper wrapper = cache.get(key);
            return wrapper != null ? wrapper.get() : null;
        }
        return null;
    }
}

6、通過注解獲取數(shù)據(jù)(注意偽代碼)

@Service
public class JTServiceImpl {
    @Service
    public void someMethod() {
        // 自調(diào)用 - 導(dǎo)致緩存失效
        String token = this.getGlobalToken("token123"); 
    }
    @Cacheable(value = "timeoutGlobalToken", key = "#globalToken")
    public String getGlobalToken(String globalToken) {
        // 實際獲取token的邏輯
    }
}

注意:注解失效原因及解決方案

原因分析:

  1. Spring AOP 工作原理

    • Spring 的緩存功能(包括 @Cacheable)是基于 AOP 代理實現(xiàn)的

    • 當(dāng)調(diào)用 @Cacheable 方法時,實際調(diào)用的是代理對象的方法,不是原始對象的方法

  2. 自調(diào)用問題(Self-Invocation)

    • 當(dāng)同一個類中的方法 A 直接調(diào)用方法 B(帶 @Cacheable 注解)時

    • 調(diào)用發(fā)生在原始對象內(nèi)部,繞過了 Spring 代理

    • 導(dǎo)致 @Cacheable 注解完全失效

解決方案:將緩存方法移到另一個Service中

// 新建專門處理緩存的服務(wù)
@Service
public class TokenCacheService {
    @Cacheable(value = "timeoutGlobalToken", key = "#globalToken")
    public String getGlobalToken(String globalToken) {
        // 實際獲取token的邏輯
        return fetchTokenFromSource(globalToken);
    }
    private String fetchTokenFromSource(String globalToken) {
        // 從數(shù)據(jù)庫/API獲取token的實現(xiàn)
    }
}

調(diào)用方:

// 原服務(wù)調(diào)用緩存服務(wù)
@Service
public class JTServiceImpl {
    @Autowired
    private TokenCacheService tokenCacheService;
    public void businessMethod() {
        // 跨類調(diào)用 - 觸發(fā)緩存
        String token = tokenCacheService.getGlobalToken("token123");
    }
}

這是一個比較常用的解決方案。 

 8、獲取所有緩存信息

@GetMapping("/cache/param")
public Map<Object, Object> getCacheEntries() {
    Cache cache = cacheManager.getCache("paramCache");
    if (cache == null) {
        return Collections.emptyMap();
    }
    com.github.benmanes.caffeine.cache.Cache<Object, Object> nativeCache = 
        (com.github.benmanes.caffeine.cache.Cache<Object, Object>) cache.getNativeCache();
    return new HashMap<>(nativeCache.asMap());
}

到此,SpringBoot 集成Caffeine實現(xiàn)一級緩存分享完成,下篇我們會繼續(xù)分享此種緩存實現(xiàn)的細(xì)節(jié),敬請期待!

到此這篇關(guān)于SpringBoot 集成Caffeine實現(xiàn)一級緩存的文章就介紹到這了,更多相關(guān)SpringBoot Caffeine一級緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

天镇县| 富民县| 青阳县| 长乐市| 乐亭县| 伊吾县| 驻马店市| 渝中区| 集安市| 白河县| 尤溪县| 夏邑县| 贡山| 泰安市| 塔城市| 靖宇县| 韶关市| 水城县| 白山市| 昌黎县| 河津市| 大埔区| 阿图什市| 浠水县| 大连市| 昌乐县| 府谷县| 新乡县| 明光市| 大庆市| 民和| 黎城县| 三原县| 北碚区| 团风县| 晋城| 龙州县| 遵化市| 崇明县| 三台县| 沁阳市|