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

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条件&
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cache 中,我们可以通过使用注解来声明缓存操作。例如,@Cacheable 注解用于表示方法的结果应该被缓存,@CacheEvict 注解用于表示缓存应该被清除,@CachePut 注解用于表示方法的结果应该被缓存,等等。这些注解都是在运行时被解析的,Spring 通过解析这些注解来确定缓存操作应该被执行的方式。 在 Spring 中,注解解析器是用于解析注解的组件。在 Spring Cache 中,注解解析器的作用是解析 @Cacheable、@CachePut、@CacheEvict 和 @Caching 注解,并将它们转换为缓存操作的定义。Spring Cache 提供了 AnnotationCacheOperationSource 类来实现这个功能。 AnnotationCacheOperationSource 类实现了 CacheOperationSource 接口,它的主要作用是解析注解并返回缓存操作的定义。在 Spring Cache 中,每个缓存操作的定义都表示为一个 CacheOperation 对象。AnnotationCacheOperationSource 类的 getCacheOperations() 方法返回一个 List<CacheOperation> 对象,表示指定方法上的所有缓存操作的定义。 AnnotationCacheOperationSource 类的核心方法是 buildCacheOperations() 方法。这个方法接收一个 MethodInvocation 对象,它描述了要执行的方法及其参数。buildCacheOperations() 方法首先检查给定的方法是否具有 @Cacheable、@CachePut、@CacheEvict 或 @Caching 注解。如果有这些注解,它将解析它们并返回一个包含缓存操作定义的 List<CacheOperation> 对象。如果没有这些注解,它将返回一个空的 List<CacheOperation> 对象。 解析注解的过程非常复杂,AnnotationCacheOperationSource 类使用了多个辅助类来完成这个过程。这些辅助类包括 AnnotationCacheAspect、CacheAnnotationParser、CacheAnnotationParserUtils 和 CacheAspectSupport。AnnotationCacheAspect 是一个切面,它拦截所有具有 @Cacheable、@CachePut、@CacheEvict 或 @Caching 注解的方法。CacheAnnotationParser 类用于解析注解并返回相应的缓存操作定义。CacheAnnotationParserUtils 类包含一些通用的注解解析方法。CacheAspectSupport 类是一个抽象类,它提供了一些通用的缓存操作方法,它的子类可以继承这些方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值