1. 程式人生 > >Spring Cache註解說明

Spring Cache註解說明

spring cache的註解使用說明

作者:YDW

地址:武漢

本文所有說明均參考spring docuemtn.如果有發現錯誤的地方,請傳送郵件給博主,博主會及時更新本文件.

@Cacheable註解

public @interface Cacheable {
    @AliasFor("cacheNames")
    String[] value() default {};

    @AliasFor("value")
    String[] cacheNames() default {};

    String key() default
""; String keyGenerator() default ""; String cacheManager() default ""; String cacheResolver() default ""; String condition() default ""; String unless() default ""; boolean sync() default false; }

引數說明

  • 註解中的引數:valuecacheNames

    首先我們需要知道在spring cache的資料結構大致可以理解為是一個Map,Map中的具體結構如下(個人理解

    ,如果有誤請聯絡博主):

    map1<cacheName,map2<cacheKey,cache>>

    所以在這個註解中的這個value和values也就是map1中的key.這個key的名字由使用者自己進行定義,沒有預設值

  • 註解中的引數:keyGenerator

    這個指的是map2中的cacheKey的生成規則的生成器,如果使用者沒有定義,那麼系統會預設使用一個生成器:defaultgenerator
    這個key的生成規則如下:

    • 如果這個方法沒有任何引數,那麼map2中的cachekey2則就就是SimpleKey.EMPTY,通過檢視原始碼,他就是一個空的Object陣列
    public class SimpleKey implements Serializable {
    public static final SimpleKey EMPTY = new SimpleKey(new Object[0]);
    ....
    • 如果是有多個引數的話,那麼生成的key的規則如下:
     public class SimpleKey implements Serializable {
     ...
    
       public SimpleKey(Object... elements) {
        Assert.notNull(elements, "Elements must not be null");
        this.params = new Object[elements.length];
        System.arraycopy(elements, 0, this.params, 0, elements.length);
        this.hashCode = Arrays.deepHashCode(this.params);
      }
    
    .....
    }

    key的值就是SimpleKey這個類.系統辨別不同的cacheKey就是通過判斷SimpleKey這個物件來辨別的.通過程式碼可以看出,它只考慮了這個方法引數的HASH值.

    • 還有一種情況就是使用者自己定義的key.這個也是這個註解中的另一個引數key();
  • 註解中的引數key

    這個引數是自己手動指定map2中的cacheKey,這個字串可以自己定義,還可以通過使用Spring的EL表示式來定義,例如:

    
    //直接使用引數中的物件isbn作為map2中的cacheKey
    @Cacheable(cacheNames="books", key="#isbn")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
    //使用引數中的物件isbn中的rawNumber欄位作為map2中的cacheKey
    @Cacheable(cacheNames="books", key="#isbn.rawNumber")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    
    //使用某個類T的hash()方法,把引數中的物件isbn傳入來構建key的值
    @Cacheable(cacheNames="books", key="T(someType).hash(#isbn)")
    public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
    

    如果這個key的引數被設定值了,那麼系統就不會使用SimpleKey來生成map2中的key

  • 引數keyGenerator, cacheManager, cacheResolver

    這些引數如果沒有配置的話,那麼系統會採用預設值

引數名 預設值 如何自定義
keyGenerator SimpleKeyGenerator 實現KeyGenerator介面
cacheManager ConcurrentMapCacheManager 實現CacheManager介面
cacheResolver 沒有預設值 實現org.springframework.cache.interceptor.CacheResolver介面

* 如果定義了CacheResolver那麼就會忽略cacheManager的引數,就像是定義了key就會忽略keyGenerator的值.

  • 註解引數:conditionunless

    舉例說明:

    //使用El表示式獲取方法中的引數name,如果name的長度小於32才使用快取
    @Cacheable(cacheNames="book", condition="#name.length() < 32")
    public Book findBook(String name)
    
    //如果unless中的條件表示式如果是true,儘管condition中的表示式通過,但是unless具有否決,相當於多個條件,
    //只有當conditon=true&unless=false的時候才會使用快取
    //unless這個引數是在這個方法執行之後,獲得返回值book,判斷book.hardback是否為true.
    @Cacheable(cacheNames="book", condition="#name.length() < 32", unless="#result.hardback")
    public Book findBook(String name)
  • 註解引數:sync

    這個引數通常的多執行緒環境下使用,原本的快取獲取是沒有任何鎖的設定和概念的,如果加了這個註解,那麼在多執行緒下獲取快取就會加上鎖,當 然,如果有鎖的話,整體系統的效能也會收到影響.

EL表示式能夠獲取上下文中的引數列表

name Location 描述 例子
methodName root object 方法的名字 root.methodName
method root object 要被執行的方法物件 root.method.name
target root object 這個方法所在的類的物件名 root.target
targetClass root object 這個方法所在的類名 root.targetClass
args root object 方法中的所有引數 root.args[0]
caches root object 快取的名字,除了本方法中的快取名字也就是Map1中的cacheName root.cahces[0].name
argument name evaluation context 引數名字,是個陣列,索引從0開始 引數別名 或者#a0 或者#p0
result evaluation context 方法的返回值,通常用於unless cachePut cache evict引數或者註解中的表示式中 result

@cachePut註解

註解的作用:更新快取

@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor)

註解裡面的引數和上面的類似,但是有一個注意點需要注意一下:

  • 官方建議這個註解不要與@Cacheable這個註解用在同一個方法上

Note that using @CachePut and @Cacheable annotations on the same method is generally strongly discouraged because they have different behaviors. While the latter causes the method execution to be skipped by using the cache, the former forces the execution in order to execute a cache update. This leads to unexpected behavior and with the exception of specific corner-cases (such as annotations having conditions that exclude them from each other), such declaration should be avoided. Note also that such condition should not rely on the result object (i.e. the #result variable) as these are validated upfront to confirm the exclusion

@CacheEvict註解

這個註解的作用就是刪除快取,例子

//allEntries表示map1中的cacheName為books對應的map的快取全部刪除
@CacheEvict(cacheNames="books", allEntries=true)
public void loadBooks(InputStream batch)
  • 這個註解中有一個引數:beforeInvocation它的值Boolean型別的.
    • 如果是true那麼就是在這個方法執行之前就把對應的快取都刪除掉

@Cacheing註解

這個註解就是為了使用多個@CachePut, @CacheEvict或者是多個@Cacheable在同一個方法上,因為多個快取中的條件表示式可能是不一樣的.例子

@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)

@CacheConfig註解

  • 這個註解是作用在類上的,主要是統一該類下面所有快取註解的一些公共配置,例如KeyGenerator