Springboot_cache缓存源码解析

Springboot与缓存cache

JSR107缓存规范

在这里插入图片描述

CachingProvider
CachingManager
Cache
Entry
Expiry ()
key() 指定缓存的Key的值,不指定默认使用方法参数的值

@CachePut 在目标方法之后调用,将返回结果添加到缓存中
@Cacheable 首先查询缓存,生成keyGenerator()
@CacheEvict 删除缓存,可以设置在调用方法前后执行
以上3个方法一般都加在Service层的党法上

cache自动配置原理

缓存服务类比其他服务应该是配置在一个自动配置类中CacheAutoConfiguration中,我们点进这个类

@Configuration
@ConditionalOnClass(CacheManager.class)
@ConditionalOnBean(CacheAspectSupport.class)
@ConditionalOnMissingBean(value = CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, HazelcastAutoConfiguration.class,
		HibernateJpaAutoConfiguration.class, RedisAutoConfiguration.class })
//这里向容器中注入了一个组件,我们点进这个组件CacheConfigurationImportSelector
@Import(CacheConfigurationImportSelector.class)
public class CacheAutoConfiguration {
  
//这是一个静态的内部类
  static class CacheConfigurationImportSelector implements ImportSelector {

    //选择让哪些缓存配置类生效,通过debug的形式,看到imports为如下值
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
      CacheType[] types = CacheType.values();
      String[] imports = new String[types.length];
      for (int i = 0; i < types.length; i++) {
        imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
      }
      //这里打个断点
      return imports;
      /**imports =
     * 0 = "org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration"
     * 1 = "org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration"
     * 2 = "org.springframework.boot.autoconfigure.cache.EhCacheCacheConfiguration"
     * 3 = "org.springframework.boot.autoconfigure.cache.HazelcastCacheConfiguration"
     * 4 = "org.springframework.boot.autoconfigure.cache.InfinispanCacheConfiguration"
     * 5 = "org.springframework.boot.autoconfigure.cache.CouchbaseCacheConfiguration"
     * 6 = "org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration"
     * 7 = "org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration"
     * 8 = "org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration"
     * 9 = "org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration"
   默认是只有SimpleCacheConfiguration 这个配置类生效(debug=true)
   控制台打印如下:
   SimpleCacheConfiguration matched:
- Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration automatic cache type (CacheCondition)
- @ConditionalOnMissingBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) did not find any beans (OnBeanCondition)
      */
    }
  }
  
//点进SimpleCacheConfiguration,这是一个配置类
@Configuration
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {
  //给容器中注入一个CacheManager缓存管理器
  //每个cacheManager都是一个ConcurrentMapCacheManager实例
  @Bean
	public ConcurrentMapCacheManager cacheManager() {
		ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
    //从配置文件中获取所有的cache的name
		List<String> cacheNames = this.cacheProperties.getCacheNames();
     //如果cache为空,cacheManager重新设置缓存名,并用一个Map将(cacheName,Cache)管理起来
		if (!cacheNames.isEmpty()) {
			cacheManager.setCacheNames(cacheNames);
		}
		return this.customizerInvoker.customize(cacheManager);
	}

  //然后我们继续点进ConcurrentMapCacheManager这个类,这个类是用来管理Caches的,点进getCache()方法
  @Override
	@Nullable
	public Cache getCache(String name) {
    // 通过传入的name在map中查找对应的Cache对象
		Cache cache = this.cacheMap.get(name);
    // 如果查找结果为空,或者这个name在ConcurrentMap中不存在
		if (cache == null && this.dynamic) {
			synchronized (this.cacheMap) {
				cache = this.cacheMap.get(name);
				if (cache == null) {
          // 那么就用线程安全的模式,按照传入的name创建一个ConcurrentMapCache实例
					cache = createConcurrentMapCache(name);
          // 然后通过Manager的Map属性将新建的cache与name管理起来
					this.cacheMap.put(name, cache);
				}
			}
		}
    // 最终获取到cache并返回出去
		return cache;
    
    
//ConcurrentMapCache是默认返回的Cache类型,我们点进去看看
//在Cache中,所有的缓存数据都是以(k,v)类型进行存储的,用一个Map store 属性进行维护
public class ConcurrentMapCache extends AbstractValueAdaptingCache {

  //获取缓存内容的方法
  protected Object lookup(Object key) {
		return this.store.get(key);
	}
  // 添加缓存内容的方法
 @Override
	public void put(Object key, @Nullable Object value) {
		this.store.put(key, toStoreValue(value));
	}
  // 删除缓存内容的方法
  @Override
  public void evict(Object key) {
    this.store.remove(key);
  }
	// 最后可以在各个方法内打个断点试一试了,用@Cacheable注解,然后在浏览器中访问2次 分别查看代码走向

常用的SpEL用到的原数据值

在@Cacheable()中可以添加以下属性

名字位置描述示例
methodNameroot object当前被调用的方法名#root.methodName
methodroot object当前被调用的方法#root.method.name
targetroot object当前被调用的目标对象#root.target
targetClassroot object当前被调用的目标对象类#root.targetClass
argsroot object当前被调用的方法参数列表#root.args[0]
cachesroot object当前方法调用使用的缓存列表
如:@Cacheable(value={“cache1,cache2”})
#root.root.cahches[0].name
argument nameroot object方法参数的名字,可以直接用#id、#a0、#p0调用,0代表索引#iban、#a0、#p0
resultroot object方法执行的返回值,@Cacheable不能调用#result

应用示例:

@Cacheable(name =“emp”,key="#id", ) 同时支持自定义keyGenerator(),用key就不用keyGenerator;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java8新特性及实战视频教程完整版Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。 Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。使用Lambda 表达式可以使代码变的更加简洁紧凑。Java8实战视频-01让方法参数具备行为能力Java8实战视频-02Lambda表达式初探Java8实战视频-03Lambda语法精讲Java8实战视频-04Lambda使用深入解析Java8实战视频-05Lambda方法推导详细解析-上.wmvJava8实战视频-06Lambda方法推导详细解析-下Java8实战视频-07Stream入门及Stream在JVM中的线程表现Java8实战视频-08Stream知识点总结Stream源码阅读Java8实战视频-09如何创建Stream上集Java8实战视频-10如何创建Stream下集.wmvJava8实战视频-11Stream之filter,distinct,skip,limit,map,flatmap详细介绍Java8实战视频-12Stream之Find,Match,Reduce详细介绍Java8实战视频-13NumericStream的详细介绍以及和Stream之间的相互转换Java8实战视频-14Stream综合练习,熟练掌握API的用法Java8实战视频-15在Optional出现之前经常遇到的空指针异常.wmvJava8实战视频-16Optional的介绍以及API的详解Java8实战视频-17Optional之flatMap,综合练习,Optional源码剖析Java8实战视频-18初识Collector体会Collector的强大Java8实战视频-19Collector使用方法深入详细介绍-01Java8实战视频-20Collector使用方法深入详细介绍-02Java8实战视频-21Collector使用方法深入详细介绍-03.wmvJava8实战视频-22Collector使用方法深入详细介绍-04Java8实战视频-23Collector原理讲解,JDK自带Collector源码深度剖析Java8实战视频-24自定义Collector,结合Stream的使用详细介绍Java8实战视频-25Parallel Stream编程体验,充分利用多核机器加快计算速度Java8实战视频-26Fork Join框架实例深入讲解Java8实战视频-27Spliterator接口源码剖析以及自定义Spliterator实现一个Stream.wmvJava8实战视频-28Default方法的介绍和简单的例子Java8实战视频-29Default方法解决多重继承冲突的三大原则详细介绍Java8实战视频-30多线程Future设计模式原理详细介绍,并且实现一个Future程序Java8实战视频-31JDK自带Future,Callable,ExecutorService介绍Java8实战视频-32实现一个异步基于事件回调的Future程序.wmvJava8实战视频-33CompletableFuture用法入门介绍Java8实战视频-34CompletableFuture之supplyAsync详细介绍Java8实战视频-35CompletableFuture流水线工作,join多个异步任务详细讲解Java8实战视频-36CompletableFuture常用API的重点详解-上Java8实战视频-37CompletableFuture常用API的重点详解-下Java8实战视频-38JDK老DateAPI存在的问题,新的DateAPI之LocalDate用法及其介绍.wmvJava8实战视频-39New Date API之LocalTime,LocalDateTime,Instant,Duration,Period详细介绍Java8实战视频-40New Date API之format和parse介绍
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值