概括
- springCache主要利用切面+拦截器去实现的
- 切面的matches方法判断是否要进行拦截
2.1 判断依据:方法上是否有Cacheable、CacheEvict、CachePut、Caching注解 - 在拦截器中进行缓存相关操作
BeanFactoryCacheOperationSourceAdvisor分析
-
继承SpringAop的AbstractBeanFactoryPointcutAdvisor类,重写其getPointcut方法,返回CacheOperationSourcePointcut
-
重点关注CacheOperationSourcePointcut#matches方法
2.1 作用:判断方法是否被拦截
2.2 在上图中发现getCacheOperationSource方法,该方法是个抽象方法,在BeanFactoryCacheOperationSourceAdvisor中初 始化CacheOperationSourcePointcut时,实现getCacheOperationSource方法
2.3 而cacheOperationSource属性是通过ProxyCachingConfiguration进行配置
2.4 AnnotationCacheOperationSource空构造方法,会默认publicMethodsOnly=true,annotationParsers为单个SpringCacheAnnotationParser
方法是否被拦截的判断AnnotationCacheOperationSource#getCacheOperations
- 判断依据:方法
- 将方法以及调用类封装new MethodClassKey(method, targetClass),成为缓存的Key
- 解析目标类方法上的缓存注解
3.1 Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
3.2 SpringCacheAnnotationParser#parseCacheAnnotations解析方法的缓存注解
拦截器CacheInterceptor分析
- 作用:缓存是否命中直接返回+查询结果缓存
- CacheInterceptor实现CacheInterceptor接口,实现invoke方法(拦截方法)
CacheAspectSupport#execute分析
- 获取CacheOperationSource
1.1 而拦截器的CacheOperationSource是通过配置得到
1.2 在切面的matches方法判断时,将缓存注解解析结果存放在attributeCache中 - 根据key获取缓存操作类CacheOperation集合
缓存操作
- 处理任何早期驱逐(待分析)
- 检查是否有匹配条件的缓存项
2.1 缓存命中,直接返回缓存
2.2 没有命中,则添加CacheableOperation请求 - 添加显示的增加缓存请求CachePutOperation
- 遍历请求集合,调用其apply方法
- 处理任何延迟的收回
查看缓存是否命中
- 生成缓存key:CacheAspectSupport#generateKey
1.1 从上图可以得知,key和keyGenerator参数是一个互斥操作
1.2 SimpleKeyGenerator#generateKey生成缓存key(keyGenerator分析见下方getCacheOperationMetadata分析)
- 根据key查询缓存CacheAspectSupport#findInCaches
2.1 context的caches属性的初始化(见下方getCaches分析)
2.2 CompositeCache#get组合缓存中获取指定缓存
(1)从本地缓存获取,如果命中则直接返回
(2)从远程缓存获取,如果命中,则先放入本地缓存,然后再返回
CacheAspectSupport#getCacheOperationMetadata
- 获取keyGenerator
1.1 如果key生成器keyGenerator为空,则getKeyGenerator方法默认生成(SingletonSupplier#obtain->SimpleKeyGenerator)
1.2 如果keyGenerator不为空,则根据beanName获取KeyGenerator的实现类 - 获取CacheResolver
2.1 通过cacheResolver属性在Spring容器中按照beanName获取CacheResolver实现类
2.2 通过cacheManager属性获取CacheManager实现类,将其封装成SimpleCacheResolver
2.3 兜底方案:operationCacheResolver = getCacheResolver();//默认
CacheAspectSupport#getCaches
- Collection<? extends Cache> caches = cacheResolver.resolveCaches(context);
- cacheResolver是如何初始化的?
2.1 CacheInterceptor实现了SmartInitializingSingleton接口,在afterSingletonsInstantiated方法中进行初始化
2.2 从Spring容器中获取CacheManager的实现类:CompositeCacheManager(自定义)
2.3 this.cacheResolver = SingletonSupplier.of(new SimpleCacheResolver(cacheManager)); - 在CacheOperationContext构造方法中this.caches = CacheAspectSupport.this.getCaches(this, metadata.cacheResolver);
后续
- 具体的缓存注解解析待分析
- 缓存操作只分析一小部分(缓存是否命中)