欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

?? 前言

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

  • @Cacheable
  • @CachePut
  • @CacheEvict

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

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

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

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

?? 一、Spring Boot 緩存核心機制概述

? 緩存抽象原理

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

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

?? 注意:

  • 這些注解只能用在 public 方法上;
  • 只有當(dāng)調(diào)用方通過 Spring 代理調(diào)用該方法時才生效(即不能在同一個類中直接調(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);
    }
}

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

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

場景說明:

當(dāng)你有一個查詢接口,數(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("【真實查詢】用戶ID:" + userId);
        return userRepository.findById(userId).orElse(null);
    }
}

參數(shù)說明:

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

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

場景說明:

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

示例代碼:

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

?? 注意:

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

? 3. @CacheEvict:清除緩存,強制刷新

場景說明:

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

示例代碼:

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

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

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

?? 參數(shù)說明:

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

?? 四、進階技巧與最佳實踐

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

可以通過實現(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è)置緩存過期時間(以 Redis 為例)

application.yml 中配置:

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

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

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

  • 使用 Caffeine 作為本地緩存,減少網(wǎng)絡(luò)開銷;
  • 使用 Redis 作為分布式緩存,確保多節(jié)點間數(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è)置不同過期時間、集群緩存

示例:防止緩存穿透

@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;
}

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

背景:

我們有一個商品服務(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 代理失效將方法抽離到另一個 Bean 中
緩存未更新沒使用 @CachePut@CacheEvict加上對應(yīng)注解
key 沖突key 重復(fù)導(dǎo)致覆蓋使用更細粒度的 key 策略
不支持序列化緩存對象未實現(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ǒng),還是搭建高并發(fā) API 平臺,都應(yīng)該合理使用緩存來優(yōu)化系統(tǒng)表現(xiàn)。

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

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

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

相關(guān)文章

  • 詳解Java對象的內(nèi)存布局

    詳解Java對象的內(nèi)存布局

    這篇文章主要介紹了Java對象的內(nèi)存布局,對對象內(nèi)存感興趣的同學(xué),一定要仔細研究下
    2021-04-04
  • Java面向?qū)ο蠛蛢?nèi)存分析圖文詳解

    Java面向?qū)ο蠛蛢?nèi)存分析圖文詳解

    這篇文章主要給大家介紹了關(guān)于Java面向?qū)ο蠛蛢?nèi)存分析的相關(guān)資料,文章可以讓初學(xué)者順利的分析內(nèi)存,更加容易的體會程序執(zhí)行過程中內(nèi)存的變化,需要的朋友可以參考下
    2021-05-05
  • Springboot整合Jasypt對配置文件中的密碼加密的步驟

    Springboot整合Jasypt對配置文件中的密碼加密的步驟

    本文給大家介紹Springboot整合Jasypt對配置文件中的密碼加密的步驟,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-09-09
  • SpringBoot2.x設(shè)置Session失效時間及失效跳轉(zhuǎn)方式

    SpringBoot2.x設(shè)置Session失效時間及失效跳轉(zhuǎn)方式

    這篇文章主要介紹了SpringBoot2.x設(shè)置Session失效時間及失效跳轉(zhuǎn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java中的數(shù)組排序方式(快速排序、冒泡排序、選擇排序)

    Java中的數(shù)組排序方式(快速排序、冒泡排序、選擇排序)

    這篇文章主要介紹了Java中的數(shù)組排序方式(快速排序、冒泡排序、選擇排序),需要的朋友可以參考下
    2014-02-02
  • 搭建Spring Boot聚合項目的實現(xiàn)示例

    搭建Spring Boot聚合項目的實現(xiàn)示例

    本文主要介紹了搭建Spring Boot聚合項目的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • Java負載均衡策略的實現(xiàn)詳解

    Java負載均衡策略的實現(xiàn)詳解

    這篇文章主要介紹了Java負載均衡策略的實現(xiàn),負載均衡在Java領(lǐng)域中有著廣泛深入的應(yīng)用,不管是大名鼎鼎的nginx,還是微服務(wù)治理組件如dubbo,feign等,負載均衡的算法在其中都有著實際的使用,需要的朋友可以參考下
    2022-07-07
  • 十分鐘速懂java知識點 System類

    十分鐘速懂java知識點 System類

    這篇文章主要介紹了java知識點System類,根據(jù)一次面試總結(jié)的,可以十分鐘速懂System類,感興趣的小伙伴們可以參考一下
    2015-12-12
  • Java線程阻塞的方法區(qū)別詳解

    Java線程阻塞的方法區(qū)別詳解

    這篇文章主要介紹了Java線程阻塞的方法區(qū)別詳解,線程阻塞是指當(dāng)一個線程無法繼續(xù)執(zhí)行時,它會進入阻塞狀態(tài),直到某個條件滿足后才能繼續(xù)執(zhí)行,線程阻塞可以通過多種方式實現(xiàn),如等待鎖、等待IO操作、等待其他線程的完成等,需要的朋友可以參考下
    2023-10-10
  • SpringBoot項目整合達夢數(shù)據(jù)庫詳解(MYSQL轉(zhuǎn)換達夢數(shù)據(jù)庫)

    SpringBoot項目整合達夢數(shù)據(jù)庫詳解(MYSQL轉(zhuǎn)換達夢數(shù)據(jù)庫)

    這篇文章主要為大家詳細介紹了MYSQL轉(zhuǎn)換達夢數(shù)據(jù)庫以及SpringBoot項目整合達夢數(shù)據(jù)庫的相關(guān)教程,文中的示例代碼講解詳細,需要的可以參考下
    2025-03-03

最新評論