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

使用Spring?Cache本地緩存示例代碼

 更新時(shí)間:2025年08月19日 09:07:12   作者:會(huì)飛的架狗師  
緩存是提高應(yīng)用程序性能的重要手段,通過將頻繁訪問的數(shù)據(jù)存儲(chǔ)在內(nèi)存中,可以減少數(shù)據(jù)庫訪問次數(shù),從而加速數(shù)據(jù)讀取,這篇文章主要介紹了使用Spring?Cache本地緩存的相關(guān)資料,需要的朋友可以參考下

一、Spring Cache簡介

Spring Cache 是 Spring 框架提供的一套聲明式緩存抽象層,通過注解方式簡化緩存操作,它通過在方法上添加注解(如 @Cacheable、@CacheEvict)來地管理緩存操作,無需手動(dòng)編寫緩存邏輯。

它支持多種緩存實(shí)現(xiàn)(如 Caffeine、Redis、EhCache),并統(tǒng)一了緩存訪問的 API。

這里需要注意兩點(diǎn):

  1. Spring Cache 只是一個(gè)聲明式的抽象緩存層,意思是它只提供了接口,不提供實(shí)現(xiàn)
  2. 具體的實(shí)現(xiàn)可以有很多,比如 Caffeine,Redis,EhCache 這些,只要實(shí)現(xiàn)了這些接口,就可以被 Spring Cache 使用。

核心特點(diǎn):

  • 基于注解的聲明式緩存
  • 支持 SpEL 表達(dá)式
  • 自動(dòng)與 Spring 生態(tài)集成
  • 支持條件緩存

二、基礎(chǔ)配置

1. 添加依賴

<!-- Spring Boot Cache Starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<!-- 如果使用Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- 如果使用caffeine -->
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>

2. 啟用緩存

在啟動(dòng)類添加@EnableCaching注解:

@SpringBootApplication
@EnableCaching
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }
}

3. 緩存配置方案

方案1:通過 yml 配置文件

spring:
  cache:
    type: caffeine
    caffeine:
      spec: maximumSize=500,expireAfterWrite=60s
    # 或者分開配置
    cache-names: users,products
    caffeine.spec: # 全局默認(rèn)配置
      maximumSize=1000,
      expireAfterAccess=30m

方案2:自定義 Bean

@Configuration  // 標(biāo)記這是一個(gè)Spring配置類
public class CacheConfig {

    /**
     * 創(chuàng)建并配置Caffeine緩存管理器
     *
     * @return CacheManager 實(shí)例,用于管理應(yīng)用中所有緩存
     *
     * 主要配置參數(shù)說明:
     * - initialCapacity: 初始緩存空間大?。ㄌ嵘跏夹阅埽?
     * - maximumSize: 緩存最大容量(基于條目數(shù))
     * - expireAfterWrite: 寫入后過期時(shí)間(數(shù)據(jù)一致性優(yōu)先場景)
     * - recordStats: 開啟統(tǒng)計(jì)功能(用于監(jiān)控和調(diào)優(yōu))
     */
    @Bean
    public CacheManager cacheManager() {
        // 創(chuàng)建Caffeine緩存管理器實(shí)例
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();

        // 配置Caffeine緩存參數(shù)
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .initialCapacity(100)      // 初始容量100個(gè)條目
                .maximumSize(1000)          // 最大緩存1000個(gè)條目,超過后按LRU淘汰
                .expireAfterWrite(10, TimeUnit.MINUTES)  // 寫入10分鐘后過期
                .recordStats());           // 啟用緩存統(tǒng)計(jì)(命中率等)

        return cacheManager;
    }

    /**
     * 創(chuàng)建短期緩存實(shí)例(獨(dú)立于主緩存管理器)
     *
     * @return Cache 實(shí)例,適用于高頻訪問的臨時(shí)數(shù)據(jù)
     *
     * 典型使用場景:
     * - 高頻訪問的臨時(shí)數(shù)據(jù)
     * - 需要快速失效的驗(yàn)證碼等
     * - 與其他緩存不同生命周期的數(shù)據(jù)
     */
    @Bean(name = "shortTermCache")  // 指定Bean名稱便于按名稱注入
    public Cache shortTermCache() {
        return Caffeine.newBuilder()
                .expireAfterWrite(1, TimeUnit.MINUTES)  // 1分鐘過期(短期存儲(chǔ))
                .maximumSize(100)                       // 最大100個(gè)條目
                .build();                               // 構(gòu)建Cache實(shí)例
    }
}

三、 緩存注解使用示例

  • @Cacheable:用于標(biāo)記方法,表示該方法將結(jié)果緩存起來,下次調(diào)用時(shí)直接從緩存中獲取結(jié)果,而不需要重新執(zhí)行方法。
  • @CacheEvict:用于標(biāo)記方法,表示該方法將清除緩存,通常用于刪除緩存。
  • @CachePut:用于標(biāo)記方法,表示該方法將更新緩存,通常用于更新緩存。
  • @Caching:用于組合多個(gè)緩存注解,可以同時(shí)使用多個(gè)緩存注解。
  • @CacheConfig:用于標(biāo)記類,表示該類中的所有方法將使用指定的緩存配置。

1.@Cacheable - 數(shù)據(jù)查詢緩存

/**
 * 根據(jù)ID獲取用戶信息(帶緩存)
 * @param id 用戶ID
 * @return 用戶對(duì)象,如果不存在返回null
 * 
 * @Cacheable 參數(shù)說明:
 * - value/cacheNames: 指定緩存名稱(對(duì)應(yīng)Caffeine配置)
 * - key: 緩存鍵,使用SpEL表達(dá)式(#參數(shù)名引用方法參數(shù))
 * - unless: 條件表達(dá)式,當(dāng)結(jié)果滿足條件時(shí)不緩存
 */
@Cacheable(value = "users", key = "#id", unless = "#result == null")
public User getUserById(Long id) {
    log.info("執(zhí)行數(shù)據(jù)庫查詢,用戶ID: {}", id);
    return userRepository.findById(id).orElse(null);
}

2.@CachePut - 更新數(shù)據(jù)并緩存

/**
 * 更新用戶信息(同時(shí)更新緩存)
 * @param user 用戶對(duì)象
 * @return 更新后的用戶對(duì)象
 * 
 * @CachePut 特點(diǎn):
 * - 總是執(zhí)行方法體
 * - 用返回值更新緩存
 * - 適用于"先寫后讀"場景
 */
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
    log.info("更新用戶數(shù)據(jù): {}", user.getId());
    return userRepository.save(user);
}

3.@CacheEvict - 刪除緩存

/**
 * 刪除用戶(同時(shí)移除緩存)
 * @param id 用戶ID
 * 
 * @CacheEvict 參數(shù)說明:
 * - beforeInvocation: 是否在方法執(zhí)行前清除緩存(默認(rèn)false)
 * - allEntries: 是否清空整個(gè)緩存區(qū)域(慎用)
 */
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
    log.info("刪除用戶: {}", id);
    userRepository.deleteById(id);
}

4. @Caching - 組合操作

組合操作允許在單個(gè)方法上同時(shí)使用多個(gè)緩存注解,以實(shí)現(xiàn)更復(fù)雜的緩存策略。

/**
* 更新用戶狀態(tài)(復(fù)雜緩存操作)
* @param userId 用戶ID
* @param status 新狀態(tài)
*
* 典型場景:
* - 更新用戶緩存
* - 同時(shí)失效用戶列表緩存
    */
    @Caching(
    put = @CachePut(value = "users", key = "#userId"),
    evict = @CacheEvict(value = "userList", allEntries = true)
    )
    public void updateUserStatus(Long userId, UserStatus status) {
    log.info("更新用戶{}狀態(tài)為{}", userId, status);
    userRepository.updateStatus(userId, status);
    }

5. 條件緩存 (condition/unless)

條件緩存允許在緩存注解中添加 SpEL 條件表達(dá)式,以控制緩存的觸發(fā)時(shí)機(jī)。

/**
 * 獲取用戶詳情(帶條件緩存)
 * @param id 用戶ID
 * 
 * 緩存條件說明:
 * - condition: 只有id>1000時(shí)才走緩存
 * - unless: 結(jié)果中status=DELETED時(shí)不緩存
 */
@Cacheable(value = "users", 
           key = "#id",
           condition = "#id > 1000",
           unless = "#result != null && #result.status == T(com.example.UserStatus).DELETED")
public User getUserDetail(Long id) {
    log.info("查詢用戶詳情: {}", id);
    return userRepository.findDetailById(id);
}

6. 異步緩存加載

/**
 * 獲取用戶訂單列表(異步緩存)
 * @param userId 用戶ID
 * 
 * @sync = true 表示:
 * - 多線程并發(fā)時(shí),只有一個(gè)線程會(huì)執(zhí)行加載
 * - 其他線程等待結(jié)果
 */
@Cacheable(value = "orders", key = "#userId", sync = true)
public List<Order> getUserOrders(Long userId) {
    log.info("加載用戶{}訂單數(shù)據(jù)...", userId);
    return orderService.getOrdersByUser(userId);
}

四、特殊場景處理

1. 緩存空值防御

/**
 * 查詢用戶(防穿透處理)
 * @param name 用戶名
 * 
 * 特殊處理:
 * - 對(duì)null結(jié)果也進(jìn)行緩存(特殊標(biāo)記對(duì)象)
 * - 設(shè)置較短過期時(shí)間(配置文件中定義)
 */
@Cacheable(value = "usersByName", 
           key = "#name",
           unless = "#result == null || #result == T(com.example.CacheConstants).NULL_OBJECT")
public User getUserByName(String name) {
    User user = userRepository.findByName(name);
    return user != null ? user : CacheConstants.NULL_OBJECT;
}

2. 復(fù)合緩存鍵

/**
 * 獲取用戶在某系統(tǒng)的權(quán)限列表
 * @param userId 用戶ID 
 * @param systemCode 系統(tǒng)編碼(如:"OA", "CRM"等)
 * @return 權(quán)限字符串集合
 * 
 * 緩存Key設(shè)計(jì)說明:
 * 1. 使用復(fù)合Key結(jié)構(gòu):`用戶ID_系統(tǒng)編碼`(如:123_OA)
 * 2. 優(yōu)點(diǎn):
 *    - 避免不同系統(tǒng)權(quán)限緩存沖突
 *    - 支持按用戶+系統(tǒng)維度獨(dú)立管理緩存
 * 3. 緩存條件:僅當(dāng)結(jié)果非空時(shí)緩存
 */
@Cacheable(value = "userPermissions", 
           key = "#userId + '_' + #systemCode",
           unless = "#result == null || #result.isEmpty()")
public Set<String> getUserSystemPermissions(Long userId, String systemCode) {
    log.debug("查詢用戶[{}]在系統(tǒng)[{}]的權(quán)限", userId, systemCode);
    return permissionService.findPermissions(userId, systemCode);
}

/**
 * 獲取用戶角色列表(帶枚舉參數(shù)的Key示例)
 * @param userId 用戶ID
 * @param roleType 角色類型枚舉
 * 
 * 枚舉類型處理技巧:
 * 1. 調(diào)用枚舉的name()方法轉(zhuǎn)換為字符串
 * 2. 最終Key格式:`userId:roleType`(如:123:ADMIN)
 */
@Cacheable(value = "userRoles", 
           key = "#userId + ':' + #roleType.name()")
public List<Role> getUserRoles(Long userId, RoleType roleType) {
    return roleService.findByUserAndType(userId, roleType);
}

五、經(jīng)驗(yàn)之談

  • 推薦為每個(gè) @Cacheable 方法添加 unless 條件防御 null
  • 業(yè)務(wù)更新方法建議同時(shí)使用 @CachePut@CacheEvict
  • 高頻訪問數(shù)據(jù)考慮設(shè)置 sync=true

總結(jié) 

到此這篇關(guān)于使用Spring Cache本地緩存的文章就介紹到這了,更多相關(guān)Spring Cache本地緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 實(shí)體類使用@Builder,導(dǎo)致@ConfigurationProperties注入屬性失敗問題

    實(shí)體類使用@Builder,導(dǎo)致@ConfigurationProperties注入屬性失敗問題

    這篇文章主要介紹了實(shí)體類使用@Builder,導(dǎo)致@ConfigurationProperties注入屬性失敗問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Intellij IDEA 查找接口實(shí)現(xiàn)類的快捷鍵

    Intellij IDEA 查找接口實(shí)現(xiàn)類的快捷鍵

    本文主要介紹了Intellij IDEA 查找接口實(shí)現(xiàn)類的快捷鍵,文中通過圖文示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-06-06
  • java實(shí)現(xiàn)簡單發(fā)送郵件功能

    java實(shí)現(xiàn)簡單發(fā)送郵件功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡單發(fā)送郵件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Spring AI集成DeepSeek的詳細(xì)步驟

    Spring AI集成DeepSeek的詳細(xì)步驟

    DeepSeek 作為一款卓越的國產(chǎn) AI 模型,越來越多的公司考慮在自己的應(yīng)用中集成,對(duì)于 Java 應(yīng)用來說,我們可以借助 Spring AI 集成 DeepSeek,非常簡單方便,本文給大家介紹了Spring AI集成DeepSeek的詳細(xì)步驟,需要的朋友可以參考下
    2025-02-02
  • Maven依賴管理的用法介紹

    Maven依賴管理的用法介紹

    依賴管理是項(xiàng)目管理中非常重要的一環(huán)。幾乎任何項(xiàng)目開發(fā)的時(shí)候需要都需要使用到庫。而這些庫很可能又依賴別的庫,這樣整個(gè)項(xiàng)目的依賴形成了一個(gè)樹狀結(jié)構(gòu),而隨著這個(gè)依賴的樹的延伸和擴(kuò)大,一系列問題就會(huì)隨之產(chǎn)生
    2022-08-08
  • IDEA報(bào)錯(cuò)java.lang.OutOfMemoryError:Java?heap?space的解決辦法

    IDEA報(bào)錯(cuò)java.lang.OutOfMemoryError:Java?heap?space的解決辦法

    這篇文章主要給大家介紹了關(guān)于IDEA報(bào)錯(cuò)java.lang.OutOfMemoryError:Java?heap?space的解決辦法,出現(xiàn)這個(gè)問題的主要原因是項(xiàng)目運(yùn)行時(shí)的堆內(nèi)存不足引起的報(bào)錯(cuò),需要的朋友可以參考下
    2024-02-02
  • Swing常用組件之多行文本區(qū)JTextArea

    Swing常用組件之多行文本區(qū)JTextArea

    這篇文章主要為大家詳細(xì)介紹了Swing常用組件之多行文本區(qū)JTextArea,感興趣的朋友可以參考一下
    2016-05-05
  • SpringBoot基于Swagger2構(gòu)建API文檔過程解析

    SpringBoot基于Swagger2構(gòu)建API文檔過程解析

    這篇文章主要介紹了SpringBoot基于Swagger2構(gòu)建API文檔過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java反射的定義和用法詳解

    Java反射的定義和用法詳解

    Java中的反射是指在程序運(yùn)行時(shí)動(dòng)態(tài)地獲取和操作類、方法、屬性等元素的能力。它使得我們可以在程序運(yùn)行時(shí)獲取一個(gè)類的信息,并對(duì)其進(jìn)行操作,需要的朋友可以參考下
    2023-05-05
  • JAVA讀取PDF、WORD文檔實(shí)例代碼

    JAVA讀取PDF、WORD文檔實(shí)例代碼

    本篇文章主要通過實(shí)例代碼介紹了JAVA讀取PDF、WORD文檔,需要的朋友可以參考下
    2017-04-04

最新評(píng)論

象州县| 方正县| 亚东县| 抚州市| 阿拉尔市| 汨罗市| 广元市| 宜宾市| 新兴县| 聂荣县| 宜城市| 苏尼特右旗| 益阳市| 泉州市| 察哈| 南宫市| 祁连县| 贞丰县| 会昌县| 葫芦岛市| 海林市| 长垣县| 英德市| 德清县| 固阳县| 长丰县| 张家港市| 安溪县| 土默特右旗| 高要市| 会昌县| 井陉县| 游戏| 宜昌市| 阿拉善盟| 宁陵县| 岳阳县| 炎陵县| 淅川县| 南陵县| 珲春市|