zoukankan      html  css  js  c++  java
  • 第九章:(2)Spring Boot 与 缓存 之 @Cacheable 注解

    一、@Cacheable 注解

      作用:将方法的运行结果进行缓存,以后再要相同的数据,直接从缓存中获取,不用调用方法:

      属性:

    value/cacheNames:指定缓存组件的名字;
      CacheManager 管理多个 Cache 组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有自己唯一一个名字
    
    key: 缓存数据使用的 key,可以用它来指定。默认是使用方法参数的值。如 id=1, 1——>方法的返回值
       使用SPEL表达式:#id 是参数 id 的值 #a0 #p0 #root.arg[0]
    
    keyGenerator:key 的生成器,可以自己指定 key 的生成器的组件 id
      key 与 keyGenerator 二选一使用
    
    cacheManager:指定缓存管理器;或者是 cacheResolver
    
    condition:判断条件,指定符合条件的情况下才缓存
    
    unless:否定,unless 指定的条件为 true,方法的返回值就不会被缓存,可以获取到结果进行判断
    	  unless = "#result == null"
    
    sync:是否使用异步模式
    

      

      代码示例:

    @Cacheable(cacheNames = {"emp"})
    public Employee getEmpById(Integer id) {
        System.out.println("查询" + id +"号员工");
        return employeeMapper.getEmpById(id);
    }

    二、@Cacheable 原理

      当在主程序类上使用了 @EnableCaching 注解就可以开启基于注解的缓存,下面来分析一下缓存的原理。

      1、自动配置类 CacheAutoConfiguration

        

         给容器中导入 CacheConfigurationImportSelector 类。

      2、CacheConfigurationImportSelector 给容器中导入一系列的缓存的配置类

        

         导入的自动配置类:

        

      3、查看那个配置类默认生效

        在配置文件中使用 debug = true 打开配置报告

         默认是 SimpleCacheConfiguration 缓存配置类生效。

      4、SimpleCacheConfiguration 作用

        SimpleCacheConfiguration 给容器中注册了一个CacheManager: ConcurrentMapCacheManager             

      5、ConcurrentMapCacheManager 作用

        ConcurrentMapCacheManager 实现了 CacheManager 接口,并重写了其中的方法:

        

         ConcurrentMapCacheManager 作用:

          (1)可以获取和创建 ConcurrentMapCache 类型的缓存组件;

          (2)他的作用是将数据保存到 ConcurrentMap 中;

      6、ConcurrentMapCache  类

        用于缓存数据的类,其中使用 ConcurrentMap 来缓存数据。

        

            存放值的方法:

        

           

    三、运行流程

      以 @Cacheable 注解为例:

      1、方法运行之前,先去查询 Cache(缓存组件),按照 cacheNames 指定的名字获取(CacheManager先获取相应的缓存),第一次获取缓存组件如果没有 Cache 组件会自动创建;

        

      2、去 Cache 中查找缓存的内容,使用一个 key(默认就是方法的参数),key 是按照某种策略生成的 ,默认是使用  keyGenerator 生成的,默认使用         SimpleKeyGenerator 生成 key;

        SimpleKeyGenerator 生成 key 的默认策略

      如果没有参数:key = new SimpleKeyGenerator
    
      如果有一个参数: key = 参数的值
    
      如果有多个参数:key = new SimpleKey(param);
    

          

      3、没有查到缓存就调用目标方法;

      4、将目标方法返回的结果,放进缓存中

      @Cacheable 标注的方法执行之前先来检查缓存中有没有这个数据,默认按照参数的值作为 key 去查询,如果没有就运行方法,并将结果放入缓存中,以后再来调用就可以直接使用缓存中的数据。

     

      核心

      (1)使用 CacheManager【ConcurrentMapCacheManager】 按照名字得到 Cache 【ConcurrentMapCache】组件;

      (2)key 是使用 keyGenerator  生成的,默认是 SimpleKeyGenerator  生成的;

    四、常用属性

      1、value/cacheNames

        指定缓存组件的名字;将方法的返回结果放在哪个缓存中,是数组的方式,可以指定多个缓存

        示例:

        @Cacheable(cacheNames = {"emp", "temp"})
        public Employee getEmpById(Integer id) {
            System.out.println("查询" + id +"号员工");
            return employeeMapper.getEmpById(id);
        }

      2、key: 缓存数据使用的 key

        支持使用 Spel 表达式

    使用SPEL表达式:#id 是参数 id 的值 #a0 #p0 #root.arg[0]
    getEmp[1] 作为 key key = "#root.methodName + '[' + #id + ']'"
    

        Spel 表达式:

        

      3、keyGenerator:key 的生成器

        key 与 keyGenerator 二选一使用,可以自定义keyGenerator

        自定义 KeyGenerator:

    @Configuration
    public class MyCacheConfig {
    
        @Bean(value = "myKeyGenerator")
        public KeyGenerator keyGenerator() {
            return new KeyGenerator(){
                @Override
                public Object generate(Object target, Method method, Object... params) {
                    return method.getName() + "[" + Arrays.asList(params).toString() + "]";
                }
            };
        }
    }
    
        @Cacheable(cacheNames = {"emp"}, keyGenerator = "myKeyGenerator")
        public Employee getEmpById(Integer id) {
            System.out.println("查询" + id +"号员工");
            return employeeMapper.getEmpById(id);
        }

      4、condition:判断条件,指定符合条件的情况下才缓存

    condition = "#a0 > 1" 当第一个参数的值 > 1 的时候才进行缓存
    condition = "#a0 > 1 and #root.methodName eq 'getEmpById'" 第一个参数的值 > 1 并且方法名是 getEmpById
    

      

      5、unless:否定,unless 指定的条件为 true,方法的返回值就不会被缓存,可以获取到结果进行判断

    unless = "#result == null" 方法返回值如果为null,结果不缓存
    unless = "#a0 == 2 " 如果第一个参数的值是2,结果不缓存
    

        示例:

        @Cacheable(cacheNames = {"emp"}, keyGenerator = "myKeyGenerator", condition = "#a0 > 1", unless = "#a0 == 2 ")
        public Employee getEmpById(Integer id) {
            System.out.println("查询" + id +"号员工");
            return employeeMapper.getEmpById(id);
        }

      6、sync:是否使用异步模式

        #unless()} is not supported 开启异步,不支持 unless

  • 相关阅读:
    IDEA 学习笔记之 Scala项目开发
    IDEA 学习笔记之 Java项目开发
    IDEA 学习笔记之 安装和基本配置
    MongoDB 学习笔记之 索引
    MongoDB 学习笔记之 删除数据,集合,数据库
    Shiro学习(13)RememberMe
    Shiro学习(12)与Spring集成
    Shiro学习(11)缓存机制
    Shiro学习(10)Session管理
    Shiro学习(9)JSP标签
  • 原文地址:https://www.cnblogs.com/niujifei/p/15730157.html
Copyright © 2011-2022 走看看