最近目标是写一个只需要本地的缓存,并且可以设置过期时间。
经过了解呢,spring有自带的缓存springcache,了解了一下发现使用是挺方便的,老早之前整合redis的时候还使用过。但是未能满足业务需求的是,无法设定过期时间。
那就准备自己实现一下子呢。
了解到,有两个玩意,CacheManager和Cache两个ConcurrentMap,前者用来管理cache的,可以通过name获取cache,后边是保存缓存内容,通过key获取缓存值。
而我的需求的过期时间细粒度并不高,相同name空间定时清空就可以了,因此只用重新实现CacheManage就可以了。
然后感觉还是心里不踏实,寻思还是看看源码吧,缕一缕实现流程,看看咱这思路有错没。
SpringAOP实现的CacheInterceptor对添加缓存注解的方法进行了拦截,所以这里就是咱分析的入口啦。
发现里面的实现是调用execute方法,显而易见是实现在父类CacheAspectSupport
里面的,咱接着看:
getCacheOperations()获取的是CacheOperation对象列表,也就是CachePutOperation、CacheableOperation、CacheEvictOperation分别对应集中注解的实体类,并且是这里是有缓存的,有就直接获取,没有就创建再返回.
然后分析其获取过程,一路找下来终于发现了咱定义的注解为何能联系起来了。
在SpringCacheAnnotationParser的parseCacheAnnotations()
方法中,去匹配Cacheable\CacheEvict\Cacheput\Caching等注解类型,构造相应对象。构造的CacheOperation
就像个实体类了,里面装有cacheNames\key\cacheManager\cacheResolver等信息了,终于联系起来了。
完事如果获取到了CacheOperations就会调用咱私有的execute,感觉是重点来了。
问题出现,流程都走完了,咱们说了半天,发现整个流程好像没咋出现之前了解到的CacheManager和Cache呢,所以还是再把目标瞄准上面私有的excute方法里面,进一步剖析,看看【从缓存取】是怎么一个样子。
上面提到咱获取到了cacheOperations集合,但是其类型还是有好几种不好统一管理。又一看,excute的入参是一个名叫CacheOperationContexts
的内部类,并且确实是由CacheOperations构造出来的,那么咱解析看看。
然后又让我发现:
setCacheManager
是在CacheAspectSupport
里面的getCacheOperationMetadata()
方法里面,初始化成功之后,会从BeanFactory通过CacheManager.class
的方式set好cacheManager,所以我们自定义cachemanager之后,加上@primary注解就可以产生作用了。
CacheAspectSupport
类还有个CachePutRequest的内部类是用于往cache里面放key和value的
至此,cache获取到了,我的目的也达到了。
1.CacheAspectSupport
类的任务很重啊,里面的execute完成了缓存的业务实现。
2.这一整套流程虽然看着复杂,但根本还是Cache
在完成任务,并用CacheManager
来管理Cache
。
3.CacheManager
和Cache
在整体流程里面的只是负责单纯的功能提供,没有去干预别的流程,所以进行改动还是没啥太大问题的。
因篇幅问题不能全部显示,请点此查看更多更全内容