1. 程式人生 > >Spring boot Caffeine快取(三)——使用註解

Spring boot Caffeine快取(三)——使用註解

註解在Spring中的應用很廣泛,幾乎成為了其標誌,這裡說下使用註解來整合快取。
cache方面的註解主要有以下5個

  • @Cacheable 觸發快取入口(這裡一般放在建立和獲取的方法上)
  • @CacheEvict 觸發快取的eviction(用於刪除的方法上)
  • @CachePut 更新快取且不影響方法執行(用於修改的方法上,該註解下的方法始終會被執行)
  • @Caching 將多個快取組合在一個方法上(該註解可以允許一個方法同時設定多個註解)
  • @CacheConfig 在類級別設定一些快取相關的共同配置(與其它快取配合使用)

上邊5個註解中目前我學習的時候使用了前三個,所以這裡主要針對前三個來展開,後邊兩個結合spring官方文件來簡單介紹下。

@Cacheable

先看看它的原始碼

public @interface Cacheable {

    /**
     * 設定要使用的cache的名字,必須提前定義好快取
     */
    @AliasFor("cacheNames")
    String[] value() default {};

    /**
     * 同value(),決定要使用那個/些快取
     */
    @AliasFor("value")
    String[] cacheNames() default {};

    /**
     * 使用SpEL表示式來設定快取的key,如果不設定預設方法上所有引數都會作為key的一部分
     */
String key() default ""; /** * 用來生成key,與key()不可以共用 */ String keyGenerator() default ""; /** * 設定要使用的cacheManager,必須先設定好cacheManager的bean,這是使用該bean的名字 */ String cacheManager() default ""; /** * 使用cacheResolver來設定使用的快取,用法同cacheManager,但是與cacheManager不可以同時使用 */
String cacheResolver() default ""; /** * 使用SpEL表示式設定出發快取的條件,在方法執行前生效 */ String condition() default ""; /** * 使用SpEL設定出發快取的條件,這裡是方法執行完生效,所以條件中可以有方法執行後的value */ String unless() default ""; /** * 用於同步的,在快取失效(過期不存在等各種原因)的時候,如果多個執行緒同時訪問被標註的方法 * 則只允許一個執行緒通過去執行方法 */ boolean sync() default false; }

現在來看下我程式碼中整合的部分

    /**
     * condition條件判斷是否要走快取,無法使用方法中出現的值(返回結果等),條件為true放入快取
     * unless是方法執行後生效,決定是否放入快取,返回true的放快取
     * */
    @Cacheable(cacheNames = "outLimit",sync = true,key = "#name",unless = "#value != null ")
    public String getCaffeineServiceTest(String name,Integer age){
        String value = name + " nihao "+ age;
        logger.info("getCaffeineServiceTest value = {}",value);
        return value;
    }
    /**
     * 如果cacheLoad生效這裡的方法主體不會被執行
     * */
    @Cacheable(cacheNames = "outLimit",key = "#name",cacheResolver = "simpleCacheResolver")
    public String addCaffeineServiceTest(String name){
        String value = name + " nihao";
        logger.info("addCaffeineServiceTest value = {}",value);
        return value;
    }
    /**
     * 使用cacheManager
     * */
    @Cacheable(cacheNames = "outLimit",sync = true,key = "#name",cacheManager = "caffeine")
    public String getCaffeineServiceTest2(String name,Integer age){
        String value = name + " nihao "+ age;
        logger.info("getCaffeineServiceTest value = {}",value);
        return value;
    }

其實看我上邊的註解後這裡沒啥好說的了,cacheResolver 這個前邊沒有講到過,這裡正好介紹下。

先看下其實現類
這裡寫圖片描述

其中SimpleCacheResolver和NamedCacheResolver是可以被我們使用的,所以這裡我給出簡單的程式碼

    @Autowired
    private CacheManager cacheManager;

    @Bean("simpleCacheResolver")
    public CacheResolver simpleCacheResolver(){
        SimpleCacheResolver resolver = new SimpleCacheResolver(cacheManager);
        return resolver;
    }

    @Bean("namedCacheResolver")
    public CacheResolver namedCacheResolver(){
        NamedCacheResolver resolver = new NamedCacheResolver(cacheManager,"outLimit");
        return resolver;
    }

CacheResolver 本質上還是載入了CacheManager,所以他和CacheManager才會互斥。

@CachePut

這是個一般用於修改方法上的註解,它的程式碼跟Cacheable基本相同,這裡不做介紹。
現在說下CachePut和Cacheable的主要區別。

@Cacheable:它的註解的方法是否被執行取決於Cacheable中的條件,方法很多時候都可能不被執行。
@CachePut:這個註解不會影響方法的執行,也就是說無論它配置的條件是什麼,方法都會被執行,更多的時候是被用到修改上。

看下程式碼

    /**
     * CachePut修改key的value,會呼叫cache的put
     * */
    @CachePut(cacheNames = "outLimit",cacheResolver = "namedCacheResolver")
    public String updateCaffeineServiceTest(String name){
        String value = name + " nihao";
        logger.info("updateCaffeineServiceTest value = {}",value);
        return value ;
    }

@CacheEvict

它跟上邊的兩個註解相比,原始碼中多了兩個屬性

public @interface CacheEvict {


    /**
     * 是否刪除快取中的所有資料,預設為false,只會刪除被註解方法中傳入的key的快取
     */
    boolean allEntries() default false;

    /**
     * 設定快取的刪除在方法執行前執行還是執行後執行。如果設定true,則無論該方法是否正常結束,快取中的值都會被刪除。
     */
    boolean beforeInvocation() default false;

}

看下我的程式碼

    /**
     * CacheEvict刪除key,會呼叫cache的evict
     * */
    @CacheEvict(cacheNames = "outLimit",key = "#name")
    public String deleteCaffeineServiceTest(String name){
        String value = name + " nihao";
        logger.info("deleteCaffeineServiceTest value = {}",value);
        return value;
    }

只是簡單的整合,沒有什麼需要特別說明的。

@Caching

它是個組合上面三個註解的註解,之前我並沒有用到,現在結合spring文件簡單說下。

原始碼

public @interface Caching {

    Cacheable[] cacheable() default {};

    CachePut[] put() default {};

    CacheEvict[] evict() default {};

}

它只是給出了三種註解的組合,並沒有給出限制條件,所以其使用也很簡單,如下

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

@CacheConfig
類級別的註解,可以設定某類中所有註解的相同部分,這個可以參考spring的類級別的@Mapping來理解。
其程式碼很簡單

public @interface CacheConfig {

    String[] cacheNames() default {};

    String keyGenerator() default "";

    String cacheManager() default "";

    String cacheResolver() default "";

}

使用如下

@CacheConfig("books")
public class BookRepositoryImpl implements BookRepository {

    @Cacheable
    public Book findBook(ISBN isbn) {...}
}

這裡說是使用books這個快取。

關於快取註解的就說到這,所有關於快取的也說完了,具體使用的時候還是看自己對快取的理解吧。