本篇文章给大家带来的内容是关于Spring Boot缓存源码的理解,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
项目里面要增加一个应用缓存,原本想着要怎么怎么来整合ehcache和springboot,做好准备配置这个配置那个,结果只需要做三件事:
pom依赖
写好一个ehcache的配置文件
在boot的application上加上注解@EnableCaching.
这就完事了,是不是很魔幻。
pom依赖
<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId> <version>2.10.5</version></dependency>
配置文件
<?xml version="1.0" encoding="UTF-8"?><ehcache> <!-- 设定缓存的默认数据过期策略 --> <defaultCache maxElementsInMemory="500" maxElementsOnDisk="2000" eternal="false" overflowToDisk="true" timeToIdleSeconds="90" timeToLiveSeconds="300" diskPersistent="false" diskExpiryThreadIntervalSeconds="300"/></ehcache>
应用上加上EnableCaching注解
@SpringBootApplication@EnableCachingpublic class EhCacheApplication { public static void main(String[] args) { SpringApplication.run(EhCacheApplication.class, args); }}
然后就可以在代码里面使用cache注解了,像这样。
@CachePut(value = "fish-ehcache", key = "#person.id") public Person save(Person person) { System.out.println("为id、key为:" + person.getId() + "数据做了缓存"); return person; } @CacheEvict(value = "fish-ehcache") public void remove(Long id) { System.out.println("删除了id、key为" + id + "的数据缓存"); } @Cacheable(value = "fish-ehcache", key = "#person.id") public Person findOne(Person person) { findCount.incrementAndGet(); System.out.println("为id、key为:" + person.getId() + "数据做了缓存"); return person; }
很方便对不对。下面,我们就来挖一挖,看看spring是怎么来做到的。主要分成两部分,一是启动的时候做了什么,二是运行的时候做了什么,三是和第三方缓存组件的适配
启动的时候做了什么、
这个得从@EnableCaching标签开始,在使用缓存功能时,在springboot的Application启动类上需要添加注解@EnableCaching,这个标签引入了
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Import({CachingConfigurationSelector.class})public @interface EnableCaching { boolean proxyTargetClass() default false; <p>本文来源gao!%daima.com搞$代*!码$网9</p> AdviceMode mode() default AdviceMode.PROXY; int order() default 2147483647;}
引入了CachingConfigurationSelector类,这个类便开启了缓存功能的配置。这个类添加了AutoProxyRegistrar.java,ProxyCachingConfiguration.java两个类。
-
AutoProxyRegistrar : 实现了ImportBeanDefinitionRegistrar接口。这里看不懂,还需要继续学习。
-
ProxyCachingConfiguration : 是一个配置类,生成了BeanFactoryCacheOperationSourceAdvisor,CacheOperationSource,和CacheInterceptor这三个bean。
CacheOperationSource封装了cache方法签名注解的解析工作,形成CacheOperation的集合。CacheInterceptor使用该集合过滤执行缓存处理。解析缓存注解的类是SpringCacheAnnotationParser,其主要方法如下
/**由CacheOperationSourcePointcut作为注解切面,会解析SpringCacheAnnotationParser.java扫描方法签名,解析被缓存注解修饰的方法,将生成一个CacheOperation的子类并将其保存到一个数组中去**/protected Collection<CacheOperation> parseCacheAnnotations(SpringCacheAnnotationParser.DefaultCacheConfig cachingConfig, AnnotatedElement ae) { Collection<CacheOperation> ops = null; //找@cacheable注解方法 Collection<Cacheable> cacheables = AnnotatedElementUtils.getAllMergedAnnotations(ae, Cacheable.class); if (!cacheables.isEmpty()) { ops = this.lazyInit(ops); Iterator var5 = cacheables.iterator(); while(var5.hasNext()) { Cacheable cacheable = (Cacheable)var5.next(); ops.add(this.parseCacheableAnnotation(ae, cachingConfig, cacheable)); } } //找@cacheEvict注解的方法 Collection<CacheEvict> evicts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CacheEvict.class); if (!evicts.isEmpty()) { ops = this.lazyInit(ops); Iterator var12 = evicts.iterator(); while(var12.hasNext()) { CacheEvict evict = (CacheEvict)var12.next(); ops.add(this.parseEvictAnnotation(ae, cachingConfig, evict)); } } //找@cachePut注解的方法 Collection<CachePut> puts = AnnotatedElementUtils.getAllMergedAnnotations(ae, CachePut.class); if (!puts.isEmpty()) { ops = this.lazyInit(ops); Iterator var14 = puts.iterator(); while(var14.hasNext()) { CachePut put = (CachePut)var14.next(); ops.add(this.parsePutAnnotation(ae, cachingConfig, put)); } } Collection<Caching> cachings = AnnotatedElementUtils.getAllMergedAnnotations(ae, Caching.class); if (!cachings.isEmpty()) { ops = this.lazyInit(ops); Iterator var16 = cachings.iterator(); while(var16.hasNext()) { Caching caching = (Caching)var16.next(); Collection<CacheOperation> cachingOps = this.parseCachingAnnotation(ae, cachingConfig, caching); if (cachingOps != null) { ops.addAll(cachingOps); } } } return ops;}