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

Spring Boot 緩存注解@Cacheable、@CachePut、@CacheEvict超詳細(xì)實(shí)戰(zhàn)

 更新時(shí)間:2025年06月30日 10:05:33   作者:一個(gè)有女朋友的程序員  
本文將帶你從零開始掌握 Spring Boot中常用的緩存注解,并通過多個(gè)實(shí)際案例演示其強(qiáng)大功能_cacheevict,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧

?? 前言

在高并發(fā)、高性能的系統(tǒng)開發(fā)中,緩存是提升接口響應(yīng)速度和降低數(shù)據(jù)庫壓力的重要手段。Spring Boot 提供了強(qiáng)大的緩存抽象層 —— spring-context-support,并結(jié)合 JSR-107 標(biāo)準(zhǔn),提供了多個(gè)緩存注解,如:

  • @Cacheable
  • @CachePut
  • @CacheEvict

這些注解可以讓我們在不侵入業(yè)務(wù)邏輯的前提下,輕松實(shí)現(xiàn)方法級別的緩存管理。

本文將帶你從零開始掌握 Spring Boot 中常用的緩存注解,并通過多個(gè)實(shí)際案例演示其強(qiáng)大功能,包括:

  • 查詢緩存優(yōu)化
  • 數(shù)據(jù)更新同步
  • 刪除緩存策略
  • 多級緩存架構(gòu)設(shè)計(jì)
  • Redis 實(shí)戰(zhàn)整合
  • 緩存穿透、擊穿、雪崩的解決方案

無論你是初學(xué)者,還是有一定經(jīng)驗(yàn)的開發(fā)者,這篇文章都能讓你快速上手 Spring Boot 緩存機(jī)制!

?? 一、Spring Boot 緩存核心機(jī)制概述

? 緩存抽象原理

Spring 的緩存機(jī)制基于 AOP 實(shí)現(xiàn),本質(zhì)上是在方法執(zhí)行前后插入緩存邏輯:

注解功能
@Cacheable先查緩存,有則返回;沒有則執(zhí)行方法并將結(jié)果緩存
@CachePut執(zhí)行方法后更新緩存(常用于新增或更新操作)
@CacheEvict清除緩存(常用于刪除或刷新緩存)

?? 注意:

  • 這些注解只能用在 public 方法上;
  • 只有當(dāng)調(diào)用方通過 Spring 代理調(diào)用該方法時(shí)才生效(即不能在同一個(gè)類中直接調(diào)用帶注解的方法);
  • 需要啟用緩存功能:@EnableCaching

??? 二、快速入門:開啟緩存支持

Step 1:添加依賴(以 Redis 為例)

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

也可以使用本地緩存如 CaffeineEhcache。

Step 2:啟用緩存

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

?? 三、三大緩存注解詳解與實(shí)戰(zhàn)

? 1. @Cacheable:查詢緩存,避免重復(fù)計(jì)算

場景說明:

當(dāng)你有一個(gè)查詢接口,數(shù)據(jù)變更頻率低,但查詢頻繁,就可以使用 @Cacheable 來緩存結(jié)果。

示例代碼:

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Cacheable(value = "users", key = "#userId")
    public User getUserById(Long userId) {
        System.out.println("【真實(shí)查詢】用戶ID:" + userId);
        return userRepository.findById(userId).orElse(null);
    }
}

參數(shù)說明:

  • value / cacheNames:指定緩存名稱,可理解為緩存區(qū)域;
  • key:緩存鍵,默認(rèn)使用參數(shù)生成;
  • unless:條件判斷,例如 unless = "#result == null" 表示結(jié)果為空時(shí)不緩存;
  • condition:根據(jù)條件決定是否緩存,例如 condition = "#userId > 0"

? 2. @CachePut:更新緩存,保持一致性

場景說明:

當(dāng)你對數(shù)據(jù)進(jìn)行了更新或新增操作,需要同步更新緩存,保證下次查詢拿到的是最新數(shù)據(jù)。

示例代碼:

@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
    return userRepository.save(user);
}

?? 注意:

  • @CachePut 總是會(huì)執(zhí)行方法體,并將結(jié)果放入緩存;
  • 常用于新增、修改等寫操作。

? 3. @CacheEvict:清除緩存,強(qiáng)制刷新

場景說明:

當(dāng)你刪除某個(gè)數(shù)據(jù)或批量清空緩存時(shí),就需要使用 @CacheEvict

示例代碼:

@CacheEvict(value = "users", key = "#userId")
public void deleteUser(Long userId) {
    userRepository.deleteById(userId);
}

清空整個(gè)緩存區(qū):

@CacheEvict(value = "users", allEntries = true)
public void clearAllUsers() {
    // 刪除所有用戶邏輯
}

?? 參數(shù)說明:

  • allEntries = true:清空該緩存區(qū)域下的所有鍵;
  • beforeInvocation = true:是否在方法執(zhí)行前清空緩存(默認(rèn) false,在方法執(zhí)行后)。

?? 四、進(jìn)階技巧與最佳實(shí)踐

? 1. 自定義緩存 Key 生成策略

可以通過實(shí)現(xiàn) KeyGenerator 接口自定義緩存 key 的生成方式:

@Bean
public KeyGenerator customKeyGenerator() {
    return (target, method, params) -> {
        StringBuilder sb = new StringBuilder();
        sb.append(target.getClass().getSimpleName());
        sb.append(method.getName());
        for (Object obj : params) {
            sb.append(obj.toString());
        }
        return sb.toString();
    };
}

然后在注解中使用:

@Cacheable(value = "users", keyGenerator = "customKeyGenerator")

? 2. 設(shè)置緩存過期時(shí)間(以 Redis 為例)

application.yml 中配置:

spring:
  redis:
    timeout: 60s
  cache:
    redis:
      time-to-live: 3600000 # 1小時(shí)

? 3. 多級緩存策略(Redis + Caffeine)

為了進(jìn)一步提升性能,可以采用“本地緩存 + 分布式緩存”的組合方案:

  • 使用 Caffeine 作為本地緩存,減少網(wǎng)絡(luò)開銷;
  • 使用 Redis 作為分布式緩存,確保多節(jié)點(diǎn)間數(shù)據(jù)一致。

示例配置:

@Configuration
public class CacheConfig {
    @Bean
    public CacheManager caffeineCacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("localUsers");
        cacheManager.setCacheBuilder(Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES));
        return cacheManager;
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

? 4. 緩存穿透、擊穿、雪崩解決方案

問題解決方案
緩存穿透緩存空值、使用布隆過濾器
緩存擊穿加互斥鎖、設(shè)置永不過期
緩存雪崩設(shè)置不同過期時(shí)間、集群緩存

示例:防止緩存穿透

@Cacheable(value = "products", key = "#productId", unless = "#result == null")
public Product getProductById(Long productId) {
    Product product = productRepository.findById(productId).orElse(null);
    if (product == null) {
        // 緩存空值,防止緩存穿透
        redisService.setWithExpire("product:" + productId, "", 60, TimeUnit.SECONDS);
    }
    return product;
}

?? 五、綜合案例:商品信息緩存實(shí)戰(zhàn)

背景:

我們有一個(gè)商品服務(wù),包含如下功能:

  • 查詢商品詳情(緩存)
  • 更新商品信息(更新緩存)
  • 刪除商品(清除緩存)

代碼示例:

@Service
public class ProductService {
    @Autowired
    private ProductRepository productRepository;
    @Cacheable(value = "products", key = "#productId")
    public Product getProductById(Long productId) {
        return productRepository.findById(productId).orElse(null);
    }
    @CachePut(value = "products", key = "#product.id")
    public Product updateProduct(Product product) {
        return productRepository.save(product);
    }
    @CacheEvict(value = "products", key = "#productId")
    public void deleteProduct(Long productId) {
        productRepository.deleteById(productId);
    }
}

?? 六、常見問題與解決方案

問題原因解決辦法
注解不生效沒加 @EnableCaching添加注解
同一類內(nèi)調(diào)用失效AOP 代理失效將方法抽離到另一個(gè) Bean 中
緩存未更新沒使用 @CachePut@CacheEvict加上對應(yīng)注解
key 沖突key 重復(fù)導(dǎo)致覆蓋使用更細(xì)粒度的 key 策略
不支持序列化緩存對象未實(shí)現(xiàn) Serializable使用 JSON 序列化或?qū)崿F(xiàn)接口

?? 七、總結(jié)對比表

注解作用是否執(zhí)行方法適用場景
@Cacheable查詢緩存有緩存則跳過方法查詢頻繁、更新少的數(shù)據(jù)
@CachePut更新緩存總是執(zhí)行方法新增/修改操作
@CacheEvict刪除緩存總是執(zhí)行方法刪除或刷新緩存

?? 八、結(jié)語

Spring Boot 的緩存注解為我們提供了一種聲明式的緩存管理方式,極大地提升了開發(fā)效率和系統(tǒng)性能。無論是構(gòu)建企業(yè)級后臺(tái)系統(tǒng),還是搭建高并發(fā) API 平臺(tái),都應(yīng)該合理使用緩存來優(yōu)化系統(tǒng)表現(xiàn)。

通過本文的學(xué)習(xí),你已經(jīng)掌握了:

  • 如何使用 @Cacheable、@CachePut@CacheEvict;
  • 如何結(jié)合 Redis 或本地緩存進(jìn)行實(shí)際應(yīng)用;
  • 如何避免緩存穿透、雪崩、擊穿等問題;
  • 如何提高系統(tǒng)的響應(yīng)速度和穩(wěn)定性。

到此這篇關(guān)于Spring Boot 緩存注解詳解:@Cacheable、@CachePut、@CacheEvict(超詳細(xì)實(shí)戰(zhàn)版)的文章就介紹到這了,更多相關(guān)Spring Boot @Cacheable、@CachePut、@CacheEvict內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合Redisson的步驟(單機(jī)版)

    SpringBoot整合Redisson的步驟(單機(jī)版)

    Redisson非常適用于分布式鎖,而我們的一項(xiàng)業(yè)務(wù)需要考慮分布式鎖這個(gè)應(yīng)用場景,于是我整合它做一個(gè)初步簡單的例子(和整合redis一樣)。
    2021-05-05
  • Java Spring之@Async原理案例詳解

    Java Spring之@Async原理案例詳解

    這篇文章主要介紹了Java Spring之@Async原理案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • Java連接Hbase的項(xiàng)目實(shí)踐

    Java連接Hbase的項(xiàng)目實(shí)踐

    HBase是基于Hadoop的高可靠、高性能、面向列的NoSQL數(shù)據(jù)庫,它提供了對海量數(shù)據(jù)的存儲(chǔ)和實(shí)時(shí)讀寫的能力,本文主要介紹了Java連接Hbase的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • java圖形驗(yàn)證碼生成工具類 web頁面校驗(yàn)驗(yàn)證碼

    java圖形驗(yàn)證碼生成工具類 web頁面校驗(yàn)驗(yàn)證碼

    這篇文章主要為大家詳細(xì)介紹了java圖形驗(yàn)證碼生成工具類,web頁面校驗(yàn)驗(yàn)證碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Java 實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲框架詳細(xì)代碼

    Java 實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲框架詳細(xì)代碼

    這篇文章主要介紹了Java 實(shí)現(xiàn)網(wǎng)絡(luò)爬蟲框架,主要是用于爬取網(wǎng)絡(luò)上一些內(nèi)容,比如超鏈接之類的,需要的朋友可以參考下面文章內(nèi)容
    2021-09-09
  • Java面向?qū)ο蟮姆庋b你了解嗎

    Java面向?qū)ο蟮姆庋b你了解嗎

    這篇文章主要為大家詳細(xì)介紹了Java面向?qū)ο蟮姆庋b,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • MyBatis?Mapper映射器的具體用法

    MyBatis?Mapper映射器的具體用法

    映射器是MyBatis中最重要的文件,映射器由Java接口和XML文件共同組成,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • java實(shí)現(xiàn)圖片的上傳與展示實(shí)例代碼

    java實(shí)現(xiàn)圖片的上傳與展示實(shí)例代碼

    這篇文章主要給大家介紹了關(guān)于java實(shí)現(xiàn)圖片的上傳與展示的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • springboot接入mq的方法示例

    springboot接入mq的方法示例

    本文主要介紹了springboot接入mq的方法示例,主要實(shí)現(xiàn)配置以及實(shí)現(xiàn)一個(gè)簡單的發(fā)送、接收消息的例子,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • SpringBoot集成SpirePDF實(shí)現(xiàn)文本替換功能

    SpringBoot集成SpirePDF實(shí)現(xiàn)文本替換功能

    SpirePDF是一個(gè)用于.NET平臺(tái)的高級PDF文檔處理庫,它提供了一套完整的API,允許開發(fā)者創(chuàng)建、編輯、轉(zhuǎn)換、合并、分割和解析PDF文件本文給大家介紹了SpringBoot集成SpirePDF實(shí)現(xiàn)文本替換功能,需要的朋友可以參考下
    2024-09-09

最新評論

德安县| 伊宁县| 佛山市| 平顶山市| 迁西县| 乐东| 那曲县| 中牟县| 嘉禾县| 株洲县| 红河县| 普定县| 龙川县| 张家港市| 德化县| 衡水市| 苗栗县| 威宁| 邻水| 白山市| 曲麻莱县| 镇坪县| 红河县| 前郭尔| 五台县| 大新县| 青海省| 云梦县| 镇安县| 苏尼特右旗| 增城市| 东光县| 青岛市| 太白县| 桦甸市| 富平县| 定兴县| 沅江市| 澄城县| 双辽市| 饶河县|