cacheable注解原理_@Cacheable的实现原理

如果你用过Spring Cache,你一定对这种配置和代码不陌生:

上面两段代码,xml是启用Cache Annotation注解并注册一个cacheManager,第二段代码在getData的时候会先去缓存里取,如果缓存没有再执行getData的真实逻辑。

那么今天的“走进科学”讲的就是Spring是怎么做到仅仅一段xml配置和一个注解就实现方法级别的自动缓存。

我们滋道Spring最牛逼的地方就在于IOC容器对于bean的管理,可以说是Spring牛逼的基石,那么画风一换,到了我们今天讨论的起点就是Spring在启动时对xml里面的各种标签进行解析,比如对应标签,负责解析的就是AnnotationDrivenCacheBeanDefinitionParser.parse方法,代码看起来很简单,根据mode属性注册Advisor Component:

展开原码

我们今天先看默认mode=proxy的情况,进入方法,发现方法里面注册了三个Bean到Context里面,分别是CacheOperationSource、CacheInterceptor和BeanFactoryCacheOperationSourceAdvisor。

熟悉AOP原理的看到Interceptor和Advisor一般都会明白大半了,并且他们共同都有一个属性cacheOperationSources,实现类是org.springframework.cache.annotation.AnnotationCacheOperationSource。

下面我们先来喵两眼这两个类,先看BeanFactoryCacheOperationSourceAdvisor,里面有一个叫CacheOperationSourcePointcut的pointcut,用来匹配方法是否需要走拦截器。通过调用之前注入进去的cacheOperationSources.getCacheOperations获取CacheOperation,代码如下:

展开原码

这样只有被CacheOperationSourcePointcut匹配的方法才会被拦截,并且通过attributeCache做了缓存。

再来看CacheInterceptor类,先看一眼继承结构:

image2015-10-16%2010%3A41%3A34.png?version=1&modificationDate=1444966464000&api=v2

这个类很简单,只是重写了MethodInterceptor的invoke方法:

展开原码

下一步是调用CacheAspectSupport

其中根据 getCacheOperations获得cacheOperations后调用的execute是关键,其中getCacheOperationSource即是之前说到的bean里面的cacheOperationSources,也就是org.springframework.cache.annotation.AnnotationCacheOperationSource,它负责三个标签的调用:@Cacheable、@CachePut和@CacheEvict。

下面喽一眼execute方法的代码:

这段代码看起来还是比较“简单”的,也是Spring Cache逻辑的核心实现了吧,根据注解执行了方法前和方法后需要的缓存操作,注意对于失效的操作分为early evictions和late evictions,对应标签@CacheEvict中的beforeInvocation属性。自此,Spring cache的逻辑算是执行完毕。

还有两点需要注意的就是

上面的实现是通过proxy的形式实现,那么对象的方法是内部调用(即 this 引用)而不是外部引用,则会导致 proxy失效,也就是注解失效。

非public方法同上

@CacheEvict标签不会对抛出异常的方法的缓存进行清空,通过将beforeInvocation设置为true,即在方法执行前

最后的话:

本篇文章并没有讲Spring的AOP实现原理以及Spring Cache的更多细节。

参考:

原文发表于2015年10月16日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值