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

Spring?@Cacheable指定失效時間實例

 更新時間:2021年12月23日 15:32:24   作者:tony樂天  
這篇文章主要介紹了Spring?@Cacheable指定失效時間實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Spring @Cacheable指定失效時間

新版本配置

@Configuration
@EnableCaching
public class RedisCacheConfig {
    @Bean
    public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
        return (builder) -> {
            for (Map.Entry<String, Duration> entry : RedisCacheName.getCacheMap().entrySet()) {
                builder.withCacheConfiguration(entry.getKey(),
                        RedisCacheConfiguration.defaultCacheConfig().entryTtl(entry.getValue()));
            }
        };
    }
 
    public static class RedisCacheName { 
        public static final String CACHE_10MIN = "CACHE_10MIN"; 
        @Getter
        private static final Map<String, Duration> cacheMap; 
        static {
            cacheMap = ImmutableMap.<String, Duration>builder().put(CACHE_10MIN, Duration.ofSeconds(10L)).build();
        } 
    } 
 
}

老版本配置

interface CacheNames{
    String CACHE_15MINS = "sssss:cache:15m";
        /** 30分鐘緩存組 */
    String CACHE_30MINS = "sssss:cache:30m";
        /** 60分鐘緩存組 */
    String CACHE_60MINS = "sssss:cache:60m";
        /** 180分鐘緩存組 */
    String CACHE_180MINS = "sssss:cache:180m";
}
 
@Component
 public class RedisCacheCustomizer
            implements CacheManagerCustomizer<RedisCacheManager> {
        /** CacheManager緩存自定義初始化比較早,盡量不要@autowired 其他spring 組件 */
        @Override
        public void customize(RedisCacheManager cacheManager) {
            // 自定義緩存名對應(yīng)的過期時間
            Map<String, Long> expires = ImmutableMap.<String, Long>builder()
                    .put(CacheNames.CACHE_15MINS, TimeUnit.MINUTES.toSeconds(15))
                    .put(CacheNames.CACHE_30MINS, TimeUnit.MINUTES.toSeconds(30))
                    .put(CacheNames.CACHE_60MINS, TimeUnit.MINUTES.toSeconds(60))
                    .put(CacheNames.CACHE_180MINS, TimeUnit.MINUTES.toSeconds(180)).build();
            // spring cache是根據(jù)cache name查找緩存過期時長的,如果找不到,則使用默認(rèn)值
            cacheManager.setDefaultExpiration(TimeUnit.MINUTES.toSeconds(30));
            cacheManager.setExpires(expires);
        }
    } 
 
  @Cacheable(key = "key", cacheNames = CacheNames.CACHE_15MINS)
    public String demo2(String key) {
        return "abc" + key;
  }

@Cacheable緩存失效時間策略默認(rèn)實現(xiàn)及擴(kuò)展

之前對Spring緩存的理解是每次設(shè)置緩存之后,重復(fù)請求會刷新緩存時間,但是問題排查閱讀源碼發(fā)現(xiàn),跟自己的理解大相徑庭。所有的你以為都僅僅是你以為?。。?!

背景

目前項目使用的spring緩存,主要是CacheManager、Cache以及@Cacheable注解,Spring現(xiàn)有的緩存注解無法單獨設(shè)置每一個注解的失效時間,Spring官方給的解釋:Spring Cache是一個抽象而不是一個緩存實現(xiàn)方案。

因此對于緩存失效時間(TTL)的策略依賴于底層緩存中間件,官方給舉例:ConcurrentMap是不支持失效時間的,而Redis是支持失效時間的。

Spring Cache Redis實現(xiàn)

Spring緩存注解@Cacheable底層的CacheManager與Cache如果使用Redis方案的話,首次設(shè)置緩存數(shù)據(jù)之后,每次重復(fù)請求相同方法讀取緩存并不會刷新失效時間,這是Spring的默認(rèn)行為(受一些緩存影響,一直以為每次讀緩存也會刷新緩存失效時間)。

可以參見源碼:

org.springframework.cache.interceptor.CacheAspectSupport#execute(org.springframework.cache.interceptor.CacheOperationInvoker, java.lang.reflect.Method, org.springframework.cache.interceptor.CacheAspectSupport.CacheOperationContexts)

private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
		// Special handling of synchronized invocation
		if (contexts.isSynchronized()) {
			CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
			if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
				Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
				Cache cache = context.getCaches().iterator().next();
				try {
					return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker))));
				}
				catch (Cache.ValueRetrievalException ex) {
					// The invoker wraps any Throwable in a ThrowableWrapper instance so we
					// can just make sure that one bubbles up the stack.
					throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause();
				}
			}
			else {
				// No caching required, only call the underlying method
				return invokeOperation(invoker);
			}
		} 
 
		// Process any early evictions
		processCacheEvicts(contexts.get(CacheEvictOperation.class), true,
				CacheOperationExpressionEvaluator.NO_RESULT);
 
		// Check if we have a cached item matching the conditions
		Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class));
 
		// Collect puts from any @Cacheable miss, if no cached item is found
		List<CachePutRequest> cachePutRequests = new LinkedList<>();
		if (cacheHit == null) {
			collectPutRequests(contexts.get(CacheableOperation.class),
					CacheOperationExpressionEvaluator.NO_RESULT, cachePutRequests);
		} 
		Object cacheValue;
		Object returnValue;
 
		if (cacheHit != null && !hasCachePut(contexts)) {
			// If there are no put requests, just use the cache hit
			cacheValue = cacheHit.get();
			returnValue = wrapCacheValue(method, cacheValue);
		}
		else {
			// Invoke the method if we don't have a cache hit
			returnValue = invokeOperation(invoker);
			cacheValue = unwrapReturnValue(returnValue);
		}
 
		// Collect any explicit @CachePuts
		collectPutRequests(contexts.get(CachePutOperation.class), cacheValue, cachePutRequests);
 
		// Process any collected put requests, either from @CachePut or a @Cacheable miss
		for (CachePutRequest cachePutRequest : cachePutRequests) {
			cachePutRequest.apply(cacheValue);
		}
 
		// Process any late evictions
		processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheValue); 
		return returnValue;
	}

因此如果我們需要自行控制緩存失效策略,就可能需要一些開發(fā)工作,具體如下。

Spring Cache 失效時間自行刷新

1:基于Spring的Cache組件進(jìn)行定制,對get方法進(jìn)行重寫,刷新過期時間。相對簡單,不難;此處不貼代碼了。

2:可以使用后臺線程進(jìn)行定時的緩存刷新,以達(dá)到刷新時間的作用。

3:使用spring data redis模塊,該模塊提供對了TTL更新策略的,可以參見:org.springframework.data.redis.core.PartialUpdate

注意:

Spring對于@Cacheable注解是由spring-context提供的,spring-context提供的緩存的抽象,是一套標(biāo)準(zhǔn)而不是實現(xiàn)。

而PartialUpdate是由于spring-data-redis提供的,spring-data-redis是一套spring關(guān)于redis的實現(xiàn)方案。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBatch從入門到精通之StepScope作用域和用法詳解

    SpringBatch從入門到精通之StepScope作用域和用法詳解

    這篇文章主要介紹了SpringBatch從入門到精通之StepScope作用域和用法詳解,主要包括IOC容器中幾種bean的作用范圍以及可能遇到的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • Spring?Boot實現(xiàn)JWT?token自動續(xù)期的實現(xiàn)

    Spring?Boot實現(xiàn)JWT?token自動續(xù)期的實現(xiàn)

    本文主要介紹了Spring?Boot實現(xiàn)JWT?token自動續(xù)期,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Spring自動裝配與掃描注解代碼詳解

    Spring自動裝配與掃描注解代碼詳解

    這篇文章主要介紹了Spring自動裝配與掃描注解代碼詳解,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Java多線程4種拒絕策略小結(jié)

    Java多線程4種拒絕策略小結(jié)

    當(dāng)線程池中的任務(wù)隊列已滿且無法再接受新的任務(wù)時,就需要采取拒絕策略來處理這種情況,本文主要介紹了Java多線程拒絕策略,包含了四種常見的拒絕策略,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 生成8位隨機(jī)不重復(fù)的數(shù)字編號的方法

    生成8位隨機(jī)不重復(fù)的數(shù)字編號的方法

    生成隨機(jī)不重復(fù)的數(shù)字編號在某些情況下也會用到,本文以生成8位隨機(jī)不重復(fù)的數(shù)字編號為例與大家分享下具體的實現(xiàn)過程,感興趣的朋友可以參考下
    2013-09-09
  • java實現(xiàn)圖形卡片排序游戲

    java實現(xiàn)圖形卡片排序游戲

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)圖形卡片排序游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-07-07
  • java使用wait()和notify()線程間通訊的實現(xiàn)

    java使用wait()和notify()線程間通訊的實現(xiàn)

    Java 線程通信是將多個獨立的線程個體進(jìn)行關(guān)聯(lián)處理,使得線程與線程之間能進(jìn)行相互通信,本文就介紹了java使用wait()和notify()線程間通訊的實現(xiàn),感興趣的可以了解一下
    2023-09-09
  • SpringBoot實現(xiàn)網(wǎng)站的登陸注冊邏輯記錄

    SpringBoot實現(xiàn)網(wǎng)站的登陸注冊邏輯記錄

    登陸注冊功能是我們?nèi)粘i_發(fā)中經(jīng)常遇到的一個功能,下面這篇文章主要給大家介紹了關(guān)于SpringBoot實現(xiàn)網(wǎng)站的登陸注冊邏輯的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • springboot使用nacos的示例詳解

    springboot使用nacos的示例詳解

    這篇文章主要介紹了springboot使用nacos的示例代碼,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • spring boot(四)之thymeleaf使用詳解

    spring boot(四)之thymeleaf使用詳解

    Thymeleaf 是一個跟 Velocity、FreeMarker 類似的模板引擎,它可以完全替代 JSP 。接下來通過本文給大家介紹spring boot(四)之thymeleaf使用詳解,需要的朋友可以參考下
    2017-05-05

最新評論

东源县| 临猗县| 繁峙县| 永善县| 康定县| 礼泉县| 襄垣县| 阿合奇县| 本溪市| 玛曲县| 施甸县| 乌兰浩特市| 新巴尔虎右旗| 焦作市| 凤阳县| 黄陵县| 陇西县| 新疆| 黄冈市| 莱州市| 石泉县| 饶平县| 铜梁县| 嘉善县| 阿瓦提县| 正定县| 津南区| 庆安县| 台安县| 马鞍山市| 建平县| 繁昌县| 安图县| 新野县| 乐昌市| 锦州市| 阳西县| 瑞丽市| 临城县| 马鞍山市| 九台市|