Spring Cache 源码分析 (4) - 缓存拦截器( CacheInterceptor)

本文详细分析了Spring Cache的缓存拦截器CacheInterceptor的工作原理,包括如何实现方法拦截,以及@CachePut、@Cacheable、@CacheEvict的缓存操作。通过CacheInterceptor、CacheOperationContexts、CacheOperationContext和CacheResolver等关键类的源码解析,揭示了Spring Cache如何获取并执行缓存操作,最终调用缓存对象Cache的相关方法完成数据存取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring Cache 源码分析 (4) - 缓存拦截器( CacheInterceptor)

缓存拦截器的实现

这一篇我们讲讲SpringCache对方法的拦截器实现,也就是CacheInterceptor。在使用SpringCache我们会比较关注的问题,为什么对一个方法使用@CachePut注解后,就可以达到缓存的效果呢?下面我们将揭开这层面纱。Spring Cache实现对方法的拦截功能,是由CacheInterceptor提供的。下面直接看看CacheInterceptor是怎么做的呢?

CacheInterceptor实现了MethodInterceptor接口,在Spring AOP中,MethodInterceptor的功能是做方法拦截。现在应该明白,为什么使用@CachePut等注解后可以实现缓存操作,因为方法被拦截处理了。CacheInterceptor的实现很简单,啥都不用啰说了,先看看代码实现。

public class CacheInterceptor extends CacheAspectSupport implements MethodInterceptor, Serializable {

	/*
	 *被拦截的方法都会调用invoke方法,不懂的可以先看看Spring AOP。
	 */
	@Override
	public Object invoke(final MethodInvocation invocation) throws Throwable {
		Method method = invocation.getMethod();
		
		//这里就是对执行方法调用的一次封装,主要是为了处理对异常的包装。
		CacheOperationInvoker aopAllianceInvoker = new CacheOperationInvoker() {
			@Override
			public Object invoke() {
				try {
					return invocation.proceed();
				}
				catch (Throwable ex) {
					throw new ThrowableWrapper(ex);
				}
			}
		};

		try {
			//真正地去处理缓存操作的执行,很显然这是父类的方法,所以我们要到父类CacheAspectSupport中去看看。
			return execute(aopAllianceInvoker, invocation.getThis(), method, invocation.getArguments());
		}
		catch (CacheOperationInvoker.ThrowableWrapper th) {
			throw th.getOriginal();
		}
	}

}

下面,我们再看看CacheAspectSupport#execute(...)这个方法中具体怎么进行缓存操作的。

protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {

	//标志Spring加载元素是否都准备好了,是否可以执行了
	if (this.initialized) {
		Class<?> targetClass = getTargetClass(target);
		//这里使用的就是CacheOperationSource,来获取执行方法上所有的缓存操作集合。如果有缓存操作则执行到execute(...),如果没有就执行invoker.invoke()直接调用执行方法了。
		Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);
		if (!CollectionUtils.isEmpty(operations)) {
			return execute(invoker, new CacheOperationContexts(operations, method, args, target, targetClass));
		}
	}

	return invoker.invoke();
}

在上面的代码中出现了CacheOperationContexts对象,这个对象只是为了便于获取每种具体缓存操作集合。我们知道所有的缓存操作CachePutOperation、CacheableOperation、CacheEvictOperation都存放在operations这个集合中,不便于获取具体的缓存操作,所以封装成了缓存操作上下文CacheOperationContexts这个类。接下来,我们继续看看核心代码,庐山真面目即将揭晓。先罗列一下@CachePut、@Cacheable、@CacheEvict的功能,再来看看代码是怎么实现的。

  1. @CachePut -- 执行方法后,将方法返回结果存放到缓存中。不管有没有缓存过,执行方法都会执行,并缓存返回结果(unless可以否决进行缓存)。(当然,这里说的缓存都要满足condition条件)
  2. @Cacheable
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值