第九章:(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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM