设为首页 加入收藏

TOP

Spring Cache框架(五)
2018-11-21 22:08:35 】 浏览:607
Tags:Spring Cache 框架
cheable miss, if no cached item is found List<CachePutRequest> cachePutRequests = new LinkedList<CachePutRequest>(); if (cacheHit == null) { collectPutRequests(contexts.get(CacheableOperation.class), CacheOperationExpressioneva luator.NO_RESULT, cachePutRequests); } Object cacheva lue; Object returnValue; if (cacheHit != null && cachePutRequests.isEmpty() && !hasCachePut(contexts)) { // If there are no put requests, just use the cache hit cacheva lue = cacheHit.get(); returnValue = wrapCacheva lue(method, cacheva lue); } else { // Invoke the method if we don't have a cache hit returnValue = invokeOperation(invoker); cacheva lue = unwrapReturnValue(returnValue); } // Collect any explicit @CachePuts collectPutRequests(contexts.get(CachePutOperation.class), cacheva lue, cachePutRequests); // Process any collected put requests, either from @CachePut or a @Cacheable miss for (CachePutRequest cachePutRequest : cachePutRequests) { cachePutRequest.apply(cacheva lue); } // Process any late evictions processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheva lue); return returnValue; }

我们的方法没有使用同步,走到 processCacheEvicts 方法。

private void processCacheEvicts(Collection<CacheOperationContext> contexts, boolean beforeInvocation, Object result) {
	for (CacheOperationContext context : contexts) {
		CacheEvictOperation operation = (CacheEvictOperation) context.metadata.operation;
		if (beforeInvocation == operation.isBeforeInvocation() && isConditionPassing(context, result)) {
			performCacheEvict(context, operation, result);
		}
	}
}

注意这个方法传入的 beforeInvocation 参数是 true,说明是方法执行前进行的操作,这里是取出 CacheEvictOperation,operation.isBeforeInvocation(),调用下面方法:

private void performCacheEvict(CacheOperationContext context, CacheEvictOperation operation, Object result) {
	Object key = null;
	for (Cache cache : context.getCaches()) {
		if (operation.isCacheWide()) {
			logInvalidating(context, operation, null);
			doClear(cache);
		}
		else {
			if (key == null) {
				key = context.generateKey(result);
			}
			logInvalidating(context, operation, key);
			doEvict(cache, key);
		}
	}
}

这里需要注意了,operation 中有个参数 cacheWide,如果使用这个参数并设置为true,则在缓存失效时,会调用 clear 方法进行全部缓存的清理,否则只对当前 key 进行 evict 操作。本文中,doEvict() 最终会调用到 ConcurrentMapCache的evict(Object key) 方法,将 key 缓存失效。

回到 execute 方法,走到 Cache.ValueWrapper cacheHit = findCachedItem(contexts.get(CacheableOperation.class)); 这一步,这里会根据当前方法是否有 CacheableOperation 注解,进行缓存的查询,如果没有命中缓存,则会调用方法拦截器 CacheInterceptor 的 proceed 方法,进行原方法的调用,得到缓存 key 对应的 value,然后通过 cachePutRequest.apply(cacheva lue) 设置缓存。

public void apply(Object result) {
	if (this.context.canPutToCache(result)) {
		for (Cache cache : this.context.getCaches()) {
			doPut(cache, this.key, result);
		}
	}
}

doPut() 方法最终对调用到 ConcurrentMapCache 的 put 方法,完成缓存的设置工作。

最后 execute 方法还有最后一步 processCacheEvicts(contexts.get(CacheEvictOperation.class), false, cacheva lue); 处理针对执行方法后缓存失效的注解策略。

优缺点

优点

  • 方便快捷高效,可直接嵌入多个现有的 cache 实现,简写了很多代码,可观性非常强。

缺点

  1. 内部调用,非 public 方法上使用注解,会导致缓存无效。由于 SpringCache 是基于 Spring AOP 的动态代理实现,由于代理本身的问题,当同一个类中调用另一个方法,会导致另一个方法的缓存不能使用,这个在编码上需要注意,避免在同一
首页 上一页 2 3 4 5 下一页 尾页 5/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇SpringBoot系列二:SpringBoot自.. 下一篇Java调试检查表

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目