領先一步
VMware 提供培訓和認證,以加速您的進度。
了解更多Spring 的快取抽象化功能自 Spring 3.1 起提供,現在是時候讓它獲得更多關注了。在這篇文章中,我想帶您了解該領域的主要改進,即 JCache (JSR-107) 註解的支援。
您可能已經聽說過,在最初提案的 13 年後,JSR-107 終於定案。對於熟悉 Spring 快取註解的人來說,下表描述了 Spring 註解與 JSR-107 對應項之間的映射關係。
Spring | JSR-107 |
---|---|
@Cacheable |
@CacheResult |
@CachePut |
@CachePut |
@CacheEvict |
@CacheRemove |
@CacheEvict(allEntries=true) |
@CacheRemoveAll |
讓我們先看看每個註解,並描述它們的使用方式。這將是一個更好的機會來了解它們支援什麼,以及您已經習慣的 Spring 註解,更重要的是這些註解帶來的新功能。
@CacheResult
與 @Cacheable
非常相似,以下使用 @CacheResult
註解重寫了 原始範例。
@CacheResult(cacheName = "books")
public Book findBook(ISBN isbn) {...}
可以使用 CacheKeyGenerator
介面自訂鍵的產生。如果沒有指定特定的實作,則預設實作根據規範,會採用所有參數,除非一個或多個參數使用 @CacheKey
註解,在這種情況下,只會使用這些參數。假設上面的方法現在需要一個額外的屬性,不應成為鍵的一部分,這就是我們使用 JCache 編寫它的方式。
@CacheResult(cacheName = "book")
public Book findBook(@CacheKey ISBN isbn, boolean checkWarehouse) { ... }
@CacheResult
帶來了例外快取的概念:每當方法執行失敗時,可以快取引發的例外,以防止再次呼叫該方法。 假設如果 ISBN 的結構無效,則會擲回 InvalidIsbnNotFoundException
。這是一個永久性失敗,永遠無法使用此參數檢索書籍。以下快取例外,以便以後使用相同無效 ISBN 的呼叫直接擲回快取的例外,而不是再次呼叫該方法。
@CacheResult(cacheName = "books", exceptionCacheName = "failures"
cachedExceptions = InvalidIsbnNotFoundException.class)
public Book findBook(@CacheKey ISBN isbn) { ... }
當然,盲目地擲回快取的例外可能會非常令人困惑,因為呼叫堆疊可能與目前的呼叫上下文不符。 我們會盡最大努力確保堆疊追蹤匹配,方法是複製具有一致呼叫堆疊的例外。
JCache 具有 CacheResolver
這個很棒的概念,允許在執行時解析要使用的快取。由於 JCache 支援常規快取和例外快取,因此要使用的 CacheResolver
實例由 CacheResolverFactory
確定。 顯而易見的預設是分別根據 cacheName
和 exceptionCacheName
屬性解析要使用的快取。 但是,也可以自訂每個操作要使用的工廠。
@CacheResult(cacheName = "books", cacheResolverFactory = MyFactory.class)
public Book findBook(@CacheKey ISBN isbn) { ... }
最後,@CacheResult
具有一個 skipGet
屬性,可以啟用該屬性以始終呼叫該方法,而不管快取的狀態如何。 這實際上與我們自己使用 @CachePut
非常相似。
雖然註解具有相同的名稱,但 JCache 中的語義卻大不相同。 我們的書的簡單更新可以這樣編寫
@CachePut(value = "books", key = "#p0")
public Book update(ISBN isbn, Book updatedBook) { ... }
雖然 JCache 會要求你這樣編寫它
@CachePut(cacheName = "books")
public void update(ISBN isbn, @CacheValue Book updatedBook) { ... }
請注意,即使 updatedBook
不應成為鍵的一部分,我們也不必將 @CacheKey
新增到第一個參數。 這是因為使用 @CacheValue
註解的參數會自動從鍵產生中排除。
對於 @CacheResult
,@CachePut
允許管理執行方法時擲回的任何例外,如果擲回的例外與註解上指定的篩選器匹配,則防止發生 put 操作。
最後,可以控制是在呼叫註解的方法之前還是之後更新快取。 當然,如果在之前更新,則不會進行例外處理。
它們分別與 @CacheEvict
和 @CacheEvict(allEntries = true)
非常相似。 @CacheRemove
具有特殊的例外處理,以防止在註解的方法擲回與註解上指定的篩選器匹配的例外時,發生逐出。
@CacheDefaults
是一個類別層級的註解,允許您共享在類別上定義的任何快取操作的通用設定。 這些是
CacheResolverFactory
CacheKeyGenerator
在下面的範例中,任何與快取相關的操作都將使用 books
快取
@CacheDefaults(cacheName = "books")
public class BookRepositoryImpl implements BookRepository {
@CacheResult
public Book findBook(@CacheKey ISBN isbn) { ... }
}
JCache 支援的實作使用我們自己的 Cache
和 CacheManager
抽象化,這意味著您可以使用現有的 CacheManager
基礎架構,並且仍然可以使用標準註解!
要啟用 Spring 快取註解的支援,您可以使用 @EnableCaching
或 <cache:annotation-driven/>
xml 元素,例如
@Configuration
@EnableCaching
public class AppConfig {
@Bean
public CacheManager cacheManager() { ...}
...
}
那麼,將標準註解的支援引入混合中需要什麼? 嗯,不多。 如果您還沒有在類別路徑中新增 JCache API 和 spring-context-support
模組,您就可以開始了。
現有的基礎架構實際上會尋找 JCache API 的存在,並且當與 Spring 的 JCache 支援一起找到時,它還將配置必要的基礎架構以支援標準註解。
#總結
長話短說,如果您已經在使用 Spring 的快取抽象化,並且想要嘗試標準註解,那麼只需向您的專案新增另外兩個依賴項即可開始使用。
想試試看嗎? 獲取 Spring 4.1 的 每日 SNAPSHOT 版本,並將 javax.cache:cache-api:1.0.0
和 org.springframework:spring-context-support:4.1.0.BUILD-SNAPSHOT
依賴項新增到您的專案。 如果您需要更多詳細信息,文件也已更新。
在下一篇文章中,我將介紹支援 JSR-107 註解如何影響我們自己的支援以及其他一些與快取相關的改進。