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

SpringBoot緩存抽象@Cacheable與緩存管理器配置方法

 更新時間:2025年03月11日 10:42:08   作者:程序媛學(xué)姐  
SpringBoot的緩存抽象通過@Cacheable注解和CacheManager接口,提供了靈活高效的緩存管理,本文詳細(xì)介紹了@Cacheable的使用技巧、緩存管理器配置方法、自定義鍵生成策略以及緩存同步與失效機(jī)制,幫助開發(fā)者構(gòu)建高效的緩存策略,優(yōu)化應(yīng)用性能,感興趣的朋友一起看看吧

引言

緩存是提升應(yīng)用性能的關(guān)鍵技術(shù),SpringBoot提供了強(qiáng)大的緩存抽象層,使開發(fā)者能夠以一致的方式操作不同的緩存實現(xiàn)。本文深入探討SpringBoot的緩存機(jī)制,重點闡述@Cacheable注解的使用技巧及緩存管理器的配置方法,幫助開發(fā)者構(gòu)建高效的緩存策略,優(yōu)化應(yīng)用性能。

一、SpringBoot緩存抽象概述

SpringBoot的緩存抽象建立在Spring Framework的緩存支持之上,提供了一套統(tǒng)一的緩存操作接口。這種抽象允許開發(fā)者在不修改業(yè)務(wù)代碼的情況下,輕松切換底層緩存實現(xiàn),如從本地緩存遷移到分布式緩存。緩存抽象的核心是CacheManager接口,它管理應(yīng)用中的緩存,而@Cacheable等注解則提供了聲明式緩存的能力。

/**
 * SpringBoot緩存示例項目啟動類
 */
@SpringBootApplication
@EnableCaching  // 啟用SpringBoot的緩存支持
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class, args);
    }
    /**
     * 配置日志以顯示緩存操作
     */
    @Bean
    public LoggingCacheErrorHandler cacheErrorHandler() {
        return new LoggingCacheErrorHandler();
    }
}

二、@Cacheable注解詳解

@Cacheable是SpringBoot緩存抽象中最常用的注解,用于標(biāo)記方法的返回值應(yīng)被緩存。當(dāng)標(biāo)記了@Cacheable的方法被調(diào)用時,SpringBoot會檢查指定的緩存是否已包含對應(yīng)鍵的值,如存在則直接返回緩存值,不執(zhí)行方法;如不存在,則執(zhí)行方法并將返回值放入緩存。這種機(jī)制顯著減少了重復(fù)計算,提升了應(yīng)用響應(yīng)速度。

/**
 * 用戶服務(wù)實現(xiàn)類,演示@Cacheable注解的基本用法
 */
@Service
public class UserServiceImpl implements UserService {
    private final UserRepository userRepository;
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    @Override
    @Cacheable(value = "users", key = "#id")
    public User getUserById(Long id) {
        // 模擬數(shù)據(jù)庫查詢的耗時操作
        try {
            Thread.sleep(2000);  // 模擬2秒的查詢延遲
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found"));
    }
}

2.1 @Cacheable的關(guān)鍵屬性

@Cacheable注解具有多個屬性,可精細(xì)控制緩存行為。value或cacheNames指定緩存名稱;key定義緩存鍵生成規(guī)則,支持SpEL表達(dá)式;condition指定緩存條件;unless定義不緩存的條件;cacheManager指定使用的緩存管理器。合理設(shè)置這些屬性可以實現(xiàn)精確的緩存控制,滿足復(fù)雜業(yè)務(wù)場景的需求。

/**
 * 產(chǎn)品服務(wù),展示@Cacheable的高級屬性用法
 */
@Service
public class ProductService {
    private final ProductRepository productRepository;
    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
    @Cacheable(
        cacheNames = "products",  // 緩存名稱
        key = "#category.concat('-').concat(#price)",  // 組合鍵
        condition = "#price > 100",  // 僅緩存價格大于100的產(chǎn)品
        unless = "#result == null",  // 不緩存null結(jié)果
        cacheManager = "productCacheManager"  // 指定緩存管理器
    )
    public List<Product> findProductsByCategoryAndPrice(String category, double price) {
        // 模擬復(fù)雜查詢
        return productRepository.findByCategoryAndPriceGreaterThan(category, price);
    }
}

三、緩存管理器配置

緩存管理器是SpringBoot緩存抽象的核心組件,負(fù)責(zé)創(chuàng)建、獲取和管理緩存實例。SpringBoot默認(rèn)使用ConcurrentMapCacheManager作為緩存管理器,它基于ConcurrentHashMap實現(xiàn),適用于開發(fā)環(huán)境或小型應(yīng)用。對于生產(chǎn)環(huán)境,通常需要配置更高性能的緩存管理器,如Caffeine、Redis或EhCache等。

/**
 * 緩存配置類,演示多種緩存管理器的配置
 */
@Configuration
public class CacheConfig {
    /**
     * 配置基于Caffeine的本地緩存管理器
     */
    @Bean
    @Primary
    public CacheManager caffeineCacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        // 全局緩存配置
        cacheManager.setCaffeine(Caffeine.newBuilder()
                .expireAfterWrite(30, TimeUnit.MINUTES)  // 寫入后30分鐘過期
                .maximumSize(1000)  // 最大緩存條目數(shù)
                .recordStats());  // 記錄緩存統(tǒng)計信息
        // 預(yù)設(shè)緩存名稱
        cacheManager.setCacheNames(Arrays.asList("users", "products", "orders"));
        return cacheManager;
    }
    /**
     * 配置Redis緩存管理器,用于分布式緩存
     */
    @Bean
    public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
        // Redis緩存配置
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(60))  // 設(shè)置TTL為60分鐘
                .disableCachingNullValues()  // 禁止緩存null值
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        // 為不同的緩存設(shè)置不同的配置
        Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
        cacheConfigurations.put("users", cacheConfiguration.entryTtl(Duration.ofMinutes(10)));
        cacheConfigurations.put("products", cacheConfiguration.entryTtl(Duration.ofHours(1)));
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(cacheConfiguration)
                .withInitialCacheConfigurations(cacheConfigurations)
                .build();
    }
}

四、自定義鍵生成策略

緩存鍵的設(shè)計直接影響緩存命中率和性能。SpringBoot默認(rèn)使用方法參數(shù)的哈希值作為緩存鍵,但在復(fù)雜場景下,可能需要自定義鍵生成策略。通過實現(xiàn)KeyGenerator接口,開發(fā)者可以控制緩存鍵的生成邏輯,例如基于參數(shù)特定字段或組合多個參數(shù)生成鍵,從而提高緩存的精確性和有效性。

/**
 * 自定義緩存鍵生成器
 */
@Component("customKeyGenerator")
public class CustomKeyGenerator implements KeyGenerator {
    @Override
    public Object generate(Object target, Method method, Object... params) {
        StringBuilder key = new StringBuilder();
        // 添加類名
        key.append(target.getClass().getSimpleName()).append(":");
        // 添加方法名
        key.append(method.getName()).append(":");
        // 處理參數(shù)
        for (Object param : params) {
            if (param instanceof User) {
                // 對于User類型參數(shù),使用其id作為鍵的一部分
                key.append(((User) param).getId());
            } else if (param != null) {
                // 對于其他參數(shù),使用其toString()方法
                key.append(param.toString());
            } else {
                key.append("null");
            }
            key.append(":");
        }
        // 移除末尾的冒號
        if (key.charAt(key.length() - 1) == ':') {
            key.deleteCharAt(key.length() - 1);
        }
        return key.toString();
    }
}
/**
 * 使用自定義鍵生成器的服務(wù)方法
 */
@Service
public class OrderService {
    @Cacheable(cacheNames = "orders", keyGenerator = "customKeyGenerator")
    public Order getOrderDetails(Long orderId, String customerCode) {
        // 業(yè)務(wù)邏輯...
        return new Order(orderId, customerCode, /* 其他訂單信息 */);
    }
}

五、緩存同步與失效策略

緩存數(shù)據(jù)與源數(shù)據(jù)的同步是緩存系統(tǒng)設(shè)計中的關(guān)鍵挑戰(zhàn)。SpringBoot提供了@CachePut和@CacheEvict注解分別用于更新緩存和移除緩存項。@CachePut在不影響方法執(zhí)行的情況下更新緩存,而@CacheEvict則負(fù)責(zé)清除緩存中的數(shù)據(jù)。通過合理使用這些注解,可以構(gòu)建出高效的緩存同步機(jī)制,確保緩存數(shù)據(jù)的一致性。

/**
 * 演示緩存同步與失效的服務(wù)類
 */
@Service
public class ProductInventoryService {
    private final ProductRepository productRepository;
    public ProductInventoryService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
    @Cacheable(cacheNames = "inventory", key = "#productId")
    public int getProductInventory(Long productId) {
        // 從數(shù)據(jù)庫查詢庫存
        return productRepository.findInventoryByProductId(productId);
    }
    @CachePut(cacheNames = "inventory", key = "#productId")
    public int updateProductInventory(Long productId, int newInventory) {
        // 更新數(shù)據(jù)庫庫存
        productRepository.updateInventory(productId, newInventory);
        return newInventory;  // 返回值將被緩存
    }
    @CacheEvict(cacheNames = "inventory", key = "#productId")
    public void invalidateInventoryCache(Long productId) {
        // 僅清除緩存,不執(zhí)行實際業(yè)務(wù)邏輯
        // 方法體可以為空,注解會處理緩存清除
    }
    // 批量清除緩存
    @CacheEvict(cacheNames = "inventory", allEntries = true)
    public void clearAllInventoryCache() {
        // 清除inventory緩存中的所有條目
        // 例如在庫存批量更新后調(diào)用
    }
}

六、SpringBoot緩存最佳實踐

在實際應(yīng)用中,緩存的使用需要遵循一些最佳實踐。避免過度緩存,只緩存熱點數(shù)據(jù)和計算密集型操作結(jié)果;設(shè)置合理的過期時間,避免緩存數(shù)據(jù)長時間不一致;為緩存配置適當(dāng)?shù)拇笮∠拗?,防止?nèi)存溢出;實現(xiàn)緩存監(jiān)控和統(tǒng)計,及時發(fā)現(xiàn)緩存問題。遵循這些實踐可以充分發(fā)揮緩存的性能優(yōu)勢,同時避免常見的緩存陷阱。

/**
 * 緩存監(jiān)控配置
 */
@Configuration
@EnableCaching
public class CacheMonitoringConfig extends CachingConfigurerSupport {
    private static final Logger logger = LoggerFactory.getLogger(CacheMonitoringConfig.class);
    /**
     * 自定義緩存解析器,添加日志記錄
     */
    @Override
    public CacheResolver cacheResolver() {
        return new LoggingCacheResolver(caffeineCacheManager());
    }
    /**
     * 自定義緩存錯誤處理器
     */
    @Override
    public CacheErrorHandler errorHandler() {
        return new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException exception, Cache cache, Object key) {
                logger.error("Cache get error for cache: {} and key: {}", cache.getName(), key, exception);
            }
            @Override
            public void handleCachePutError(RuntimeException exception, Cache cache, Object key, Object value) {
                logger.error("Cache put error for cache: {} and key: {}", cache.getName(), key, exception);
            }
            @Override
            public void handleCacheEvictError(RuntimeException exception, Cache cache, Object key) {
                logger.error("Cache evict error for cache: {} and key: {}", cache.getName(), key, exception);
            }
            @Override
            public void handleCacheClearError(RuntimeException exception, Cache cache) {
                logger.error("Cache clear error for cache: {}", cache.getName(), exception);
            }
        };
    }
    /**
     * 緩存統(tǒng)計信息收集任務(wù)
     */
    @Scheduled(fixedRate = 60000)  // 每分鐘執(zhí)行一次
    public void reportCacheStatistics() {
        CaffeineCacheManager cacheManager = (CaffeineCacheManager) caffeineCacheManager();
        cacheManager.getCacheNames().forEach(cacheName -> {
            com.github.benmanes.caffeine.cache.Cache<Object, Object> nativeCache = 
                    (com.github.benmanes.caffeine.cache.Cache<Object, Object>) 
                    ((CaffeineCache) cacheManager.getCache(cacheName)).getNativeCache();
            CacheStats stats = nativeCache.stats();
            logger.info("Cache: {} stats - Hit rate: {}, Eviction count: {}, Load time: {}ms",
                    cacheName,
                    String.format("%.2f", stats.hitRate() * 100) + "%",
                    stats.evictionCount(),
                    stats.totalLoadTime() / 1_000_000);
        });
    }
}

總結(jié)

SpringBoot的緩存抽象為Java應(yīng)用提供了強(qiáng)大而靈活的緩存支持。通過@Cacheable注解和多樣化的緩存管理器配置,開發(fā)者可以輕松實現(xiàn)高效的緩存策略。本文詳細(xì)闡述了緩存抽象的核心概念、@Cacheable注解的使用技巧、緩存管理器的配置方法、自定義鍵生成策略以及緩存同步與失效機(jī)制。在實際應(yīng)用中,開發(fā)者應(yīng)根據(jù)業(yè)務(wù)需求選擇合適的緩存實現(xiàn),并遵循緩存最佳實踐,如合理設(shè)置緩存大小和過期時間、實施緩存監(jiān)控與統(tǒng)計等。恰當(dāng)?shù)厥褂肧pringBoot緩存不僅能顯著提升應(yīng)用性能,還能減輕數(shù)據(jù)庫負(fù)擔(dān),提高系統(tǒng)整體響應(yīng)能力和用戶體驗。

到此這篇關(guān)于SpringBoot緩存抽象:@Cacheable與緩存管理器配置的文章就介紹到這了,更多相關(guān)SpringBoot @Cacheable緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java線程池之線程復(fù)用原理全面解析

    Java線程池之線程復(fù)用原理全面解析

    這篇文章主要介紹了Java線程池之線程復(fù)用原理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 詳解Java中Object?類的使用

    詳解Java中Object?類的使用

    Java的Object?類是所有類的父類,也就是說?Java?的所有類都繼承了?Object,本文主要來和大家講講Object?類的使用,感興趣的可以了解一下
    2023-05-05
  • 解決SpringBoot application.yaml文件配置schema 無法執(zhí)行sql問題

    解決SpringBoot application.yaml文件配置schema 無法執(zhí)行sql問題

    這篇文章主要介紹了解決SpringBoot application.yaml文件配置schema 無法執(zhí)行sql問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 一文帶你徹底剖析Java中Synchronized原理

    一文帶你徹底剖析Java中Synchronized原理

    Synchronized是Java中的隱式鎖,它的獲取鎖和釋放鎖都是隱式的,完全交由JVM幫助我們操作,在了解Synchronized關(guān)鍵字之前,首先要學(xué)習(xí)的知識點就是Java的對象結(jié)構(gòu),本文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • IntelliJ IDEA2020.2.2創(chuàng)建Servlet方法及404問題

    IntelliJ IDEA2020.2.2創(chuàng)建Servlet方法及404問題

    這篇文章主要介紹了IntelliJ IDEA2020.2.2創(chuàng)建Servlet方法及404問題,這里小編使用的2020.2.2企業(yè)破解版本,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09
  • java加密MD5實現(xiàn)及密碼驗證代碼實例

    java加密MD5實現(xiàn)及密碼驗證代碼實例

    這篇文章主要介紹了java加密MD5實現(xiàn)及密碼驗證代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • java統(tǒng)計漢字字?jǐn)?shù)的方法示例

    java統(tǒng)計漢字字?jǐn)?shù)的方法示例

    這篇文章主要介紹了java統(tǒng)計漢字字?jǐn)?shù)的方法,結(jié)合實例形式分析了java正則判定、字符串遍歷及統(tǒng)計相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • SpringMVC編程使用Controller接口實現(xiàn)控制器實例代碼

    SpringMVC編程使用Controller接口實現(xiàn)控制器實例代碼

    這篇文章主要介紹了SpringMVC編程使用Controller接口實現(xiàn)控制器實例代碼,具有一定參考價值,需要的朋友可以參考下。
    2017-11-11
  • 用IDEA創(chuàng)建SpringBoot項目的詳細(xì)步驟記錄

    用IDEA創(chuàng)建SpringBoot項目的詳細(xì)步驟記錄

    Idea有著非常簡便的Spring Boot新建過程,同時依靠pom自動下載依賴,下面這篇文章主要給大家介紹了關(guān)于用IDEA創(chuàng)建SpringBoot項目的詳細(xì)步驟,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-08-08
  • spring一個項目多個模塊聚合打包問題解決方案(最新推薦)

    spring一個項目多個模塊聚合打包問題解決方案(最新推薦)

    最近遇到個需求,針對后端解耦模塊較多的項目,想在云端啟動時簡潔些只啟動一個jar文件的情景,本文重點給大家介紹spring一個項目多個模塊聚合打包問題解決方案,感興趣的朋友一起看看吧
    2023-09-09

最新評論