SpringBoot使用Spring緩存註解

聲明:Spring緩存註解的使用非常簡單,主要是理解,所以本文主要以示例+註釋(圖片版)進行說明,核心部分
           會給出文字版;當然本人測試時完整的項目代碼會放在GitHub上,鏈接見本文末。


目錄

啓用Spring緩存註解技術

Spring緩存註解總體介紹

緩存註解的常用屬性(以示例進行說明)

key

condition

cacheNames

unless

allEntries

beforeInvocation

緩存註解使用在返回值爲viod方法上的測試


背景簡述: 
       自Spring3.1開始,Spring就自帶了對緩存的支持。我們可以直接使用Spring緩存技術將某些數據放入本機的緩存中;Spring緩存技術也可以搭配其他緩存中間件(如Redis等)進行使用,將某些數據寫入到緩存中間件(緩存中間件可能在其他機器上)中。


啓用Spring緩存註解技術

第一步:確認Spring版本不低於3.1。

注:本人用的是SpringBoot2.1.2.RELEASE,對應的Spring版本爲5.1.4.RELEASE。

第二步:在SpringBoot啓動類上啓用Spring緩存技術。

第三步:在類上或類中的方法上使用緩存註解。

注:這個【類】指的是注入了Spring容器中的。如果沒有注入,那麼在該類上或該類中的緩存註解是不會生效的


Spring緩存註解總體介紹

Spring提供的緩存註解有:

常用的註解有:@EnableCaching、@Cacheable、@CacheEvict、@CachePut、@Caching、@CacheConfig。

提示:本部分提到的key,可見本文下面關於緩存註解各屬性的介紹。

@EnableCaching:開關性註解,在項目啓動類或某個配置類上使用此註解後,則表示允許使用註解的方式進行緩存操作,如:

@Cacheable可用於類或方法上;在目標方法執行前,會根據key先去緩存中查詢看是否有數據,有就直接
                         返回緩存中的key對應的value值。不再執行目標方法;無則執行目標方法,並將方法的返回值
                        作爲value,並以鍵值對的形式存入緩存,
如:

@CachePut可用於類或方法上;在執行完目標方法後,並將方法的返回值作爲value,並以鍵值對的形式存入緩存中,如:

@CacheEvict可用於類或方法上;在執行完目標方法後,清除緩存中對應key的數據(如果緩存
                          中有對應key的數據緩存的話)
,如:

@Caching此註解即可作爲@Cacheable、@CacheEvict、@CachePut三種註解中的的任何一種或幾種來使用,如:

@CacheConfig@Cacheable、@CacheEvict、@CachePut這三個註解的cacheNames屬性是必
                             填項(或value屬性是必填項,因爲value屬性是cacheNames的別名屬性);如果上述
                             三種註解都用的是同一個cacheNames的話,那麼在每此都寫cacheNames的話,
                             就會顯得麻煩。如將@CacheConfig註解就是來配置一些公共屬性(如:cacheNames、
                             keyGenerator等)的值的,如:


緩存註解的常用屬性(以示例進行說明)

key

        key的來源可分爲三類,分別是:默認的、keyGenerator生成的、主動指定的。

下面在具體代碼中進行說明,注意閱讀註釋說明!

默認key

keyGenerator生成key

編寫配置類、定製化key生成器:

import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**
 * 定製化CachingConfigurer
 *
 * @author JustryDeng
 * @date 2019/4/11 16:26
 */
@Configuration
public class MyCachingConfigurer extends CachingConfigurerSupport {

    /**
     * 定製化key生成器
     *
     * 設置  全限定類名 + 方法名 + 參數名 共同組成 key
     *
     * @return key生成器
     * @date 2019/4/12 14:09
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (Object target, Method method, Object... params) -> {
            StringBuilder sb = new StringBuilder(16);
            sb.append(target.getClass().getName());
            sb.append("_");
            sb.append(method.getName());
            sb.append("_");
            for (int i = 0; i < params.length; i++) {
                sb.append(params[i]);
                if (i < params.length - 1) {
                    sb.append(",");
                }
            }
            return sb.toString();
        };
    }
}

此時,若使用緩存註解時不指定key屬性,那麼就會默認採用Key生成器生成的註解:

主動指定key

condition

       在激活註解功能前,進行condition驗證,如果condition結果爲true,則表明驗證通過,緩存註解生效;否則緩存註解不生效

condition作用時機在緩存註解檢查緩存中是否有對應的key-value 之前。
                                     注:緩存註解檢查緩存中是否有對應的key-value 在 運行目標方法之前,
                                            所以 condition作用時機也在運行目標方法之前。

實驗示例

驗證:

cacheNames

         通過cacheNames對數據進行隔離,不同cacheName下可以有相同的key。也可稱呼cacheName爲命名空間。

下面驗證的是當同時制定多個cacheName時,從哪一個cacheName取數據。

這裏先給出結論

若屬性cacheNames(或屬性value)指定了多個命名空間;

 

  1. 當進行緩存存儲時,會在這些命名空間下都存一份key-value。

  2. 當進行緩存讀取時,會按照cacheNames值裏命名空間的順序,挨個挨個從命名空間中查找對應的key,如果在某個命名空間中查找打了對應的緩存,就不會再查找排在後面的命名空間,也不會再執行對應方法,直接返回緩存中的value值

實驗示例

驗證:

unless

       功能是:是否令註解(在方法執行後的功能)不生效;若unless的結果爲true,則(方法執行後的功能)不生效;若unless的結果爲false,則(方法執行後的)功能生效

注:unless默認爲"",即相當於默認爲false。

unless的作用時機目標方法運行後。
                                 注:如果(因爲直接從緩存中獲取到了數據,而導致)目標方法沒有被執行,那麼unless字段不生效

舉例說明一
        對於@Cacheable註解,在執行目標方法前,如果從緩存中查詢到了數據,那麼直接返回緩存中的數據;如果從 緩存中沒有查詢到數據,那麼執行目標方法,目標方法執行完畢之後,判斷unless的結果,若unless的結果爲true,那麼不緩存方法的返回值;若unless的結果爲false,那麼緩存方法的返回值。

舉例說明二
        對於@CachePut註解,在目標方法執行完畢之後,判斷unless的結果,若unless的結果爲true,那麼不緩存方法的返回值;若unless的結果爲false,那麼緩存方法的返回值。

注:因爲unless的作用時機是在方法運行完畢後,所以我們可以用SpEL表達式#result 來獲取方法的返回值

實驗示例

驗證:

說明:本人跑了幾次此測試方法,每次隨機產生的key(從代碼裏面可知,本人已入參參數爲key)都是之前緩存
           裏面沒有的,也就是說每次都會執行目標方法;發現大於等於5000的隨機數都存入緩存彙總了;而小
           於5000的隨機數則沒有。

allEntries

        此屬性主要出現在@CacheEvict註解中,表示是否清除指定命名空間中的所有數據,默認爲false。

beforeInvocation

        此屬性主要出現在@CacheEvict註解中,表示 是否在目標方法執行前使 此註解生效。 默認爲false,即:目標方法執行完畢後此註解生效。

緩存註解使用在返回值爲viod方法上的測試

結論是緩存註解作用於void方法上,仍然會向緩存中進行存儲,不過鍵值對中的value爲null。

實驗示例

驗證:

 

筆者寄語

        關於Spring緩存註解的其他一些屬性、用法等這裏就不再一一敘述了,感興趣的可自行查詢相關資料或閱讀源碼進行測試

 

^_^ 如有不當之處,歡迎指正

^_^ 測試代碼託管鏈接 
               https://github.com/JustryDeng/CommonRepository

^_^ 本文已經被收錄進《程序員成長筆記(五)》,筆者JustryDeng

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章