@Cacheable注解在spring3中的使用-實現緩存

sakaliu83 8年前發布 | 18K 次閱讀 Java開發

來自: http://blog.csdn.net//chenleixing/article/details/44815443



       在軟件開發中使用緩存已經有一個非常久的歷史了。緩存是一種很好的設計思想,一旦你用了他,你將會發現他確實很有用。Spring3.1版本的核心對緩存做了實現。在Java推出Annotation特性之前,實現緩存的一個難點在于它與業務邏輯代碼的耦合性太強。
       然而,Spring3.1中使用@Cacheable 和@CacheEvict實現緩存在某種程度上解決了這個問題,基本思想是在方法加上@Cacheable注解,這個方法的返回值
將具有緩存特性。
       @Cacheable注解可以用在方法或者類級別。當他應用于方法級別的時候,就是如上所說的緩存返回值了。當應用在類級別的時候,這個類的所有方法的
返回值都將被緩存。

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Cacheable (value =  "employee" )
public class EmployeeDAO {
 
   public Person findEmployee(String firstName, String surname,  int age) {
 
     return new Person(firstName, surname, age);
   }
 
   public Person findAnotherEmployee(String firstName, String surname,  int age) {
 
     return new Person(firstName, surname, age);
   }
}

       @Cacheable注解有三個參數,value是必須的,還有key和condition。第一個參數,也就是value指明了緩存將被存到什么地方

?
1
2
3
4
5
@Cacheable (value =  "employee" )
  public Person findEmployee(String firstName, String surname,  int age) {
 
    return new Person(firstName, surname, age);
  }

       任何存儲在緩存中的數據為了高速訪問都需要一個key。Spring默認使用被@Cacheable注解的方法的簽名來作為key,當然你可以重寫key,自定義key可以使用SpEL表達式。

?
1
2
3
4
<span style= "font-size:14px;" > @Cacheable (value =  "employee" , key =  "#surname" )</span>    public Person findEmployeeBySurname(String firstName, String surname,  int age) {
 
     return new Person(firstName, surname, age);
   }

       在findEmployeeBySurname()的注解中"#surname"是一個SpEL表達式,他將使用findEmployeeBySurname()方法中的surname參數作為key。


       @Cacheable的最后一個參數是condition(可選),同樣的,也是引用一個SpEL表達式。但是這個參數將指明方法的返回結果是否被緩存。

?
1
2
3
4
5
@Cacheable (value =  "employee" , condition =  "#age < 25" )
  public Person findEmployeeByAge(String firstName, String surname,  int age) {
 
    return new Person(firstName, surname, age);
  }

上面的例子中,只有年齡小于25的時候才被緩存。

在快速看完了如何使用緩存后,我們接下來看看緩存帶來的效果。
?
1
2
3
4
5
6
7
8
@Test
   public void testCache() {
 
     Person employee1 = instance.findEmployee( "John" ,  "Smith" ,  33 );
     Person employee2 = instance.findEmployee( "John" ,  "Smith" ,  33 );
 
     assertEquals(employee1, employee2);
   }

</div>

</div>

       上面的例子很簡單,第一次調用findEmployee,findEmployee方法將被執行,Spring將他的返回值一個person對象存入緩存。第二次調用findEmployee的時候findEmployee將不被執行,Spring直接將緩存中的數據作為返回值返回。所以employee1 和employee2引用了同樣的對象。

       而下面的例子中,我們將年齡小于25作為緩存條件,就將得到不同的結果。
?
1
2
3
4
5
6
7
8
@Test
  public void testCacheWithAgeAsCondition() {
 
    Person employee1 = instance.findEmployeeByAge( "John" ,  "Smith" ,  33 );
    Person employee2 = instance.findEmployeeByAge( "John" ,  "Smith" ,  33 );
 
    assertEquals(employee1, employee2);
  }

</div>

</div>


</div>

       下面的例子我們在findEmployeeBySurname的方法的注解中自定義了key,我們使用了自定義的key生成方式,以確保不同的surname將會指向不同的人。看下面的程序:
</div>

?

1
2
3
4
5
6
7
8
@Test
  public void testCacheOnSurnameAsKey() {
 
    Person employee1 = instance.findEmployeeBySurname( "John" ,  "Smith" ,  22 );
    Person employee2 = instance.findEmployeeBySurname( "Jack" ,  "Smith" ,  55 );
 
    assertEquals(employee1, employee2);
  }

</div>

</div>

       我們想找到兩個不同的人,但是兩個人的surname是相同的,你將發現兩次調用返回了相同的結果,這不是Spring的問題,而是我們的cache key的生成方式有問題。所以在我們定義key的時候要小心注意key的生成策略,避免造成這種問題。

        最后總結一下流程,當執行到一個被@Cacheable注解的方法時,Spring首先檢查condition條件是否滿足,如果不滿足,執行方法,返回;如果滿足,在value所命名的緩存空間中查找使用key存儲的對象,如果找到,將找到的結果返回,如果沒有找到執行方法,將方法的返回值以key-對象的方式存入value緩存中,然后方法返回。

上文僅僅是@Cacheable的使用方法,但是我們怎么使用@CacheEvict注解來清除緩存呢?另外,還有一個問題,如何選擇一個緩存的實現,并配置Spring的緩存呢?欲知后事如何,且聽下回分解。
 本文由用戶 sakaliu83 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!