SpringBoot接入CaffeineCache

spring-context提供了Cache集成抽象組件方式, 如: CacheManager接口、 Cache接口, @Cacheable@EnableCaching  等。java

spring-context-support則提供了多種具體緩存實現。git

  • @Cacheable  每次執行前都會檢查Cache中是否存在相同key的緩存元素,若是存在直接從緩存中獲取結果進行返回,不然纔會執行並將返回結果存入指定的緩存中。
  • @CachePut  也能夠聲明一個方法支持緩存功能。在執行前不會去檢查緩存中是否存在以前執行過的結果,而是每次都會執行該方法,並將執行結果以鍵值對的形式存入指定的緩存中(使用@CachePut時能夠指定的屬性跟@Cacheable是同樣的)
  • @CacheEvict 是用來標註在須要清除緩存元素的方法或類上的。當標記在一個類上時表示其中全部的方法的執行都會觸發緩存的清除操做。@CacheEvict能夠指定的屬性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的語義與@Cacheable對應的屬性相似。
    • value 表示清除操做是發生在哪些Cache上的(對應Cache的名稱);
    • key   表示須要清除的是哪一個key,如未指定則會使用默認策略生成的key;
    • condition  表示清除操做發生的條件。  
    • allEntries  是boolean類型,表示是否須要清除緩存中的全部元素。默認爲false,表示不須要。當指定了allEntries爲true時,Spring Cache將忽略指定的key。 清除操做默認是在對應方法成功執行以後觸發的,即方法若是由於拋出異常而未能成功返回時也不會觸發清除操做。
    • beforeInvocation  能夠改變觸發清除操做的時間,當咱們指定該屬性值爲true時,Spring會在調用該方法以前清除緩存中的指定元素。
  •  @Caching  能夠在一個方法或者類上同時指定多個Spring Cache相關的註解。其擁有三個屬性:cacheable、put和evict,分別用於指定@Cacheable、@CachePut和@CacheEvict。

key自定義策略是指: github

  • 經過Spring的EL表達式來指定key。這裏的EL表達式可使用方法參數及它們對應的屬性。使用方法參數時能夠直接使用「#參數名」或「#p參數index」 或「#參數名.屬性」或「#p參數index.屬性」
    @Cacheable(value="users", key="#id")
       public User find(Integer id) {
          return null;
       }
     
       @Cacheable(value="users", key="#p0")
       public User find(Integer id) {
          return null;
       }
     
       @Cacheable(value="users", key="#user.id")
       public User find(User user) {
          return null;
       }
     
       @Cacheable(value="users", key="#p0.id")
       public User find(User user) {
          return null;
       }
  • 除了上述使用方法參數做爲key以外,Spring還爲咱們提供了一個root對象能夠用來生成key。經過該root對象能夠獲取到如下信息。

    屬性名稱spring

    描述數組

    示例緩存

    methodNameless

    當前方法名ide

    #root.methodNamespring-boot

    method測試

    當前方法

    #root.method.name

    target

    當前被調用的對象

    #root.target

    targetClass

    當前被調用的對象的class

    #root.targetClass

    args

    當前方法參數組成的數組

    #root.args[0]

    caches

    當前被調用的方法使用的Cache

    #root.caches[0].name

     當要使用root對象的屬性做爲key時咱們也能夠將「#root」省略,由於Spring默認使用的就是root對象的屬性。 

    @Cacheable(value={"users", "xxx"}, key="caches[1].name")   
       public User find(User user) {      
         return null;   
       }

 本文以CaffeineCache接入爲例。

  1. 增長jar包引用
    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
           <dependency>
                <groupId>com.github.ben-manes.caffeine</groupId>
                <artifactId>caffeine</artifactId>
            </dependency>
  2. 在啓動類上聲明@EnableCaching,並裝載CaffeineCacheManager
    CacheName須要提早確認並設置,會在AbstractCacheResolver.resolveCaches從CacheManager中獲取
    import org.springframework.cache.CacheManager;
    import org.springframework.cache.caffeine.CaffeineCacheManager;
    
    import com.github.benmanes.caffeine.cache.CacheLoader;
    import com.github.benmanes.caffeine.cache.Caffeine;
    
        @Bean
        public CacheManager cacheManager() {
            CaffeineCacheManager cacheManager = new CaffeineCacheManager();
            Caffeine caffeine = Caffeine.newBuilder()
                    // cache的初始容量值
                    .initialCapacity(100)
                    // maximumSize用來控制cache的最大緩存數量,maximumSize和maximumWeight不能夠同時使用,
                    .maximumSize(200).expireAfterWrite(5, TimeUnit.SECONDS);
                    // 使用refreshAfterWrite必需要設置cacheLoader,可是不能用,由於每一個cacheLoader要有差別
                    //.refreshAfterWrite(2, TimeUnit.SECONDS);
          //  cacheManager.setCacheLoader(cacheLoader());
          //  cacheManager.setAllowNullValues(false);
    
            cacheManager.setCaffeine(caffeine);
            cacheManager.setCacheNames(Arrays.asList("activityCache", "propCache", "eventCache"));
            return cacheManager;
        }
    
       /**
         * 必需要指定這個Bean,refreshAfterWrite這個配置屬性才生效
         */
       private CacheLoader<Object, Object> cacheLoader() {
            CacheLoader<Object, Object> cacheLoader = new CacheLoader<Object, Object>() {
                @Override
                public Object load(Object key) throws Exception {
                    return null;
                }
    
                // 重寫這個方法將oldValue值返回,進而刷新緩存
                @Override
                public Object reload(Object key, Object oldValue) throws Exception {
                    return oldValue;
                }
            };
            return cacheLoader;
    }
  3. 使用時: 指定Cache名稱、自定義Key值、 前置&後置條件
    @Cacheable(value = "activityCache", key = "#actId" ,  condition ="#actId != '' ", unless = "#result == null")
        public Activity findById(String actId) {
            return mongoTemplate.findById(actId, Activity.class);
        }
  • expireAfterWrite 指定項在必定時間內沒有建立/覆蓋時,會移除該key,下次取的時候會從新loading;
  • refreshAfterWrite必須指定一個CacheLoader建立緩存或者最近一次更新緩存後通過固定時間間隔,從指定的CacheLoader中reload刷新緩存。通常不適用註解的方式
  • @Cacheable 不能配置  condition = "#result != null" ,由於這個註解在進入方法前去檢測condition,而這時尚未result,確定爲null;形成一直不能緩存的狀況。-----測試正確

  • 想要達到參數爲空和返回值爲空不緩存(後者會出現緩存穿透的現象)當設置cacheManager.setAllowNullValues(false)時<默認true>,targetMethod返回null直接報錯:

    因此只能使用unless 

相關文章
相關標籤/搜索