Spring緩衝註解@Cacheable、@CacheEvict、@CachePut使用

來源:互聯網
上載者:User

 從3.1開始,Spring引入了對Cache的支援。其使用方法和原理都類似於Spring對交易管理的支援。Spring Cache是作用在方法上的,其核心思想是這樣的:當我們在調用一個緩衝方法時會把該方法參數和返回結果作為一個索引值對存放在緩衝中,等到下次利用同樣的參數來調用該方法時將不再執行該方法,而是直接從緩衝中擷取結果進行返回。所以在使用Spring Cache的時候我們要保證我們緩衝的方法對於相同的方法參數要有相同的返回結果。

       使用Spring Cache需要我們做兩方面的事:

n  聲明某些方法使用緩衝

n  配置Spring對Cache的支援

       和Spring對交易管理的支援一樣,Spring對Cache的支援也有基於註解和基於XML配置兩種方式。下面我們先來看看基於註解的方式。

  1       基於註解的支援

       Spring為我們提供了幾個註解來支援Spring Cache。其核心主要是@Cacheable和@CacheEvict。使用@Cacheable標記的方法在執行後Spring Cache將緩衝其返回結果,而使用@CacheEvict標記的方法會在方法執行前或者執行後移除Spring Cache中的某些元素。下面我們將來詳細介紹一下Spring基於註解對Cache的支援所提供的幾個註解。 1.1    @Cacheable

       @Cacheable可以標記在一個方法上,也可以標記在一個類上。當標記在一個方法上時表示該方法是支援緩衝的,當標記在一個類上時則表示該類所有的方法都是支援緩衝的。對於一個支援緩衝的方法,Spring會在其被調用後將其傳回值緩衝起來,以保證下次利用同樣的參數來執行該方法時可以直接從緩衝中擷取結果,而不需要再次執行該方法。Spring在緩衝方法的傳回值時是以索引值對進行緩衝的,值就是方法的返回結果,至於鍵的話,Spring又支援兩種策略,預設策略和自訂策略,這個稍後會進行說明。需要注意的是當一個支援緩衝的方法在對象內部被調用時是不會觸發緩衝功能的。@Cacheable可以指定三個屬性,value、key和condition。 1.1.1  value屬性指定Cache名稱

       value屬性是必須指定的,其表示當前方法的傳回值是會被緩衝在哪個Cache上的,對應Cache的名稱。其可以是一個Cache也可以是多個Cache,當需要指定多個Cache時其是一個數組。

   @Cacheable("cache1")//Cache是發生在cache1上的

   public User find(Integer id) {

      returnnull;

   }

 

   @Cacheable({"cache1", "cache2"})//Cache是發生在cache1和cache2上的

   public User find(Integer id) {

      returnnull;

   }

  1.1.2  使用key屬性自訂key

       key屬性是用來指定Spring緩衝方法的返回結果時對應的key的。該屬性支援SpringEL運算式。當我們沒有指定該屬性時,Spring將使用預設策略產生key。我們這裡先來看看自訂策略,至於預設策略會在後文單獨介紹。

       自訂策略是指我們可以通過Spring的EL運算式來指定我們的key。這裡的EL運算式可以使用方法參數及它們對應的屬性。使用方法參數時我們可以直接使用“#參數名”或者“#p參數index”。下面是幾個使用參數作為key的樣本。

   @Cacheable(value="users", key="#id")

   public User find(Integer id) {

      returnnull;

   }

 

   @Cacheable(value="users", key="#p0")

   public User find(Integer id) {

      returnnull;

   }

 

   @Cacheable(value="users", key="#user.id")

   public User find(User user) {

      returnnull;

   }

 

   @Cacheable(value="users", key="#p0.id")

   public User find(User user) {

      returnnull;

   }

 

       除了上述使用方法參數作為key之外,Spring還為我們提供了一個root對象可以用來產生key。通過該root對象我們可以擷取到以下資訊。

屬性名稱

描述

樣本

methodName

當前方法名

#root.methodName

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) {

      returnnull;

   }

  1.1.3  condition屬性指定發生的條件

       有的時候我們可能並不希望緩衝一個方法所有的返回結果。通過condition屬性可以實現這一功能。condition屬性預設為空白,表示將緩衝所有的調用情形。其值是通過SpringEL運算式來指定的,當為true時表示進行緩衝處理;當為false時表示不進行緩衝處理,即每次調用該方法時該方法都會執行一次。如下樣本表示只有當user的id為偶數時才會進行緩衝。

   @Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")

   public User find(User user) {

      System.out.println("find user by user " + user);

      return user;

   }

  1.2     @CachePut

       在支援Spring Cache的環境下,對於使用@Cacheable標註的方法,Spring在每次執行前都會檢查Cache中是否存在相同key的緩衝元素,如果存在就不再執行該方法,而是直接從緩衝中擷取結果進行返回,否則才會執行並將返回結果存入指定的緩衝中。@CachePut也可以聲明一個方法支援緩衝功能。與@Cacheable不同的是使用@CachePut標註的方法在執行前不會去檢查緩衝中是否存在之前執行過的結果,而是每次都會執行該方法,並將執行結果以索引值對的形式存入指定的緩衝中。

       @CachePut也可以標註在類上和方法上。使用@CachePut時我們可以指定的屬性跟@Cacheable是一樣的。

   @CachePut("users")//每次都會執行方法,並將結果存入指定的緩衝中

   public User find(Integer id) {

      returnnull;

   }

  1.3     @CacheEvict

       @CacheEvict是用來標註在需要清除緩衝元素的方法或類上的。當標記在一個類上時表示其中所有的方法的執行都會觸發緩衝的清除操作。@CacheEvict可以指定的屬性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的語義與@Cacheable對應的屬性類似。即value表示清除操作是發生在哪些Cache上的(對應Cache的名稱);key表示需要清除的是哪個key,如未指定則會使用預設策略產生的key;condition表示清除操作發生的條件。下面我們來介紹一下新出現的兩個屬性allEntries和beforeInvocation。 1.3.1  allEntries屬性

       allEntries是boolean類型,表示是否需要清除緩衝中的所有元素。預設為false,表示不需要。當指定了allEntries為true時,Spring Cache將忽略指定的key。有的時候我們需要Cache一下清除所有的元素,這比一個一個清除元素更有效率。

   @CacheEvict(value="users", allEntries=true)

   public void delete(Integer id) {

      System.out.println("delete user by id: " + id);

   }

  1.3.2  beforeInvocation屬性

       清除操作預設是在對應方法成功執行之後觸發的,即方法如果因為拋出異常而未能成功返回時也不會觸發清除操作。使用beforeInvocation可以改變觸發清除操作的時間,當我們指定該屬性值為true時,Spring會在調用該方法之前清除緩衝中的指定元素。

   @CacheEvict(value="users", beforeInvocation=true)

   public void delete(Integer id) {

      System.out.println("delete user by id: " + id);

   }

 

       其實除了使用@CacheEvict清除緩衝元素外,當我們使用Ehcache作為實現時,我們也可以配置Ehcache自身的驅除策略,其是通過Ehcache的設定檔來指定的。由於Ehcache不是本文描述的重點,這裡就不多贅述了,想瞭解更多關於Ehcache的資訊,請查看我關於Ehcache的專欄。

  1.4     @Caching

       @Caching註解可以讓我們在一個方法或者類上同時指定多個Spring Cache相關的註解。其擁有三個屬性:cacheable、put和evict,分別用於指定@Cacheable、@CachePut和@CacheEvict。

   @Caching(cacheable = @Cacheable("users"), evict = { @CacheEvict("cache2"),

         @CacheEvict(value = "cache3", allEntries = true) })

   public User find(Integer id) {

      returnnull;

   }

  1.5     使用自訂註解

       Spring允許我們在配置可快取的方法時使用自訂的註解,前提是自訂的註解上必須使用對應的註解進行標註。如我們有如下這麼一個使用@Cacheable進行標註的自訂註解。

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Cacheable(value="users")

public @interface MyCacheable {

 

}

       那麼在我們需要緩衝的方法上使用@MyCacheable進行標註也可以達到同樣的效果。

   @MyCacheable

   public User findById(Integer id) {

      System.out.println("find user by id: " + id);

      User user = new User();

      user.setId(id);

      user.setName("Name" + id);

      return user;

   }

  2       配置Spring對Cache的支援 2.1     聲明對Cache的支援 2.1.1  基於註解

       配置Spring對基於註解的Cache的支援,首先我們需要在Spring的設定檔中引入cache命名空間,其次通過<cache:annotation-driven />就可以啟用Spring對基於註解的Cache的支援。

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xmlns:cache="http://www.springframework.org/schema/cache"

   xsi:schemaLocation="http://www.springframework.org/schema/beans

     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

     http://www.springframework.org/schema/cache

     http://www.springframework.org/schema/cache/spring-cache.xsd">

 

   <cache:annotation-driven/>

 

</beans>

 

       <cache:annotation-driven/>有一個cache-manager屬性用來指定當前所使用的CacheManager對應的bean的名稱,預設是cacheManager,所以當我們的CacheManager的id為cacheManager時我們可以不指定該參數,否則就需要我們指定了。

       <cache:annotation-driven/>還可以指定一個mode屬性,可選值有proxy和aspectj。預設是使用proxy。當mode為proxy時,只有緩衝方法在外部被調用的時候Spring Cache才會發生作用,這也就意味著如果一個緩衝方法在其聲明對象內部被調用時Spring Cache是不會發生作用的。而mode為aspectj時就不會有這種問題。另外使用proxy時,只有public方法上的@Cacheable等標註才會起作用,如果需要非public方法上的方法也可以使用Spring Cache時把mode設定為aspectj。

       此外,<cache:annotation-driven/>還可以指定一個proxy-target-class屬性,表示是否要代理class,預設為false。我們前面提到的@Cacheable、@cacheEvict等也可以標註在介面上,這對於基於介面的代理來說是沒有什麼問題的,但是需要注意的是當我們設定proxy-target-class為true或者mode為aspectj時,是直接基於class進行操作的,定義在介面上的@Cacheable等Cache註解不會被識別到,那對應的Spring Cache也不會起作用了。

       需要注意的是<cache:annotation-driven/>只會去尋找定義在同一個ApplicationContext下的@Cacheable等緩衝註解。

  2.1.2  基於XML配置

       除了使用註解來聲明對Cache的支援外,Spring還支援使用XML來聲明對Cache的支援。這主要是通過類似於aop:advice的cache:advice來進行的。在cache命名空間下定義了一個cache:advice元素用來定義一個對於Cache的advice。其需要指定一個cache-manager屬性,預設為cacheManager。cache:advice下面可以指定多個cache:caching元素,其有點類似於使用註解時的@Caching註解。cache:caching元素下又可以指定cache:cacheable、cache:cache-put和cache:cache-evict元素,它們類似於使用註解時的@Cacheable、@CachePut和@CacheEvict。下面來看一個樣本:

   <cache:advice id="cacheAdvice" cache-manager="cacheManager">

      <cache:caching cache="users">

         <cache:cacheable method="findById" key="#p0"/>

         <cache:cacheable method="find" key="#user.id"/>

         <cache:cache-evict method="deleteAll" all-entries="true"/>

      </cache:caching>

   </cache:advice>

 

       上面配置定義了一個名為cacheAdvice的cache:advice,其中指定了將緩衝findById方法和find方法到名為users的緩衝中。這裡的方法還可以使用萬用字元“*”,比如“find*”表示任何以“find”開始的方法。

       有了cache:advice之後,我們還需要引入aop命名空間,然後通過aop:config指定定義好的cacheAdvice要應用在哪些pointcut上。如:

   <aop:config proxy-target-class="false">

      <aop:adviso

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.