Начиная с версии 4.1, абстракция кэширования Spring обеспечивает полную поддержку аннотаций стандарта JCache (JSR-107): @CacheResult
, @CachePut
, @CacheRemove
и @CacheRemoveAll
, а также аннотации @CacheDefaults
, @CacheKey
и @CacheValue
. Можно использовать эти аннотации даже без переноса вашего хранилища кэша на JSR-107. Внутренняя реализация использует абстракцию кэширования Spring и предусматривает реализации CacheResolver
и KeyGenerator
по умолчанию, которые соответствуют спецификации. Иными словами, если вы уже используете абстракцию кэширования Spring, то можете перейти на эти стандартизированные аннотации без изменения хранилища кэша (или конфигурации, если на то пошло).
Краткая характеристика
Для тех, кто знаком с аннотациями кэширования Spring, в следующей таблице описаны основные различия между аннотациями Spring и их аналогами из JSR-107:
Spring | JSR-107 | Комментарий |
---|---|---|
|
|
Довольно похожи. Аннотация |
|
|
В то время как Spring обновляет кэш результатом вызова метода, JCache требует, чтобы он был передан в качестве аргумента, аннотированного |
|
|
Довольно похожи. Аннотация |
|
|
См. аннотацию |
|
|
Позволяет конфигурировать те же понятия аналогичным образом. |
В JCache есть понятие javax.cache.annotation.CacheResolver
, которое идентично интерфейсу CacheResolver
из Spring, за исключением того, что JCache поддерживает лишь один кэш. По умолчанию простая реализация извлекает используемый кэш на основе имени, объявленного в аннотации. Следует отметить, что если в аннотации не задано имя кэша, то автоматически генерируется имя по умолчанию. Для получения дополнительной информации см. javadoc по @CacheResult#cacheName()
.
Экземпляры CacheResolver
извлекаются фабрикой CacheResolverFactory
. Можно настроить эту фабрику для каждой операции кэширования, как показано в следующем примере:
@CacheResult(cacheNames="books", cacheResolverFactory=MyCacheResolverFactory.class) (1)
public Book findBook(ISBN isbn)
- Настраиваем фабрику для этой операции.
Ключи генерируются при помощи javax.cache.annotation.CacheKeyGenerator
, который служит той же цели, что и KeyGenerator
для Spring. По умолчанию учитываются все аргументы метода, если хотя бы один параметр не аннотирован при помощи @CacheKey
. Это похоже на объявление генерации кастомных ключей для Spring. Например, ниже приведены идентичные операции, одна из которых использует абстракцию Spring, а другая – JCache:
@Cacheable(cacheNames="books", key="#isbn")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
@CacheResult(cacheName="books")
public Book findBook(@CacheKey ISBN isbn, boolean checkWarehouse, boolean includeUsed)
Также можно задать CacheKeyResolver
в операции, аналогично тому, как задается CacheResolverFactory
.
JCache может управлять исключениями, генерируемыми аннотированными методами. Таким образом, обновление кэша можно предотвратить, но также это можно использовать для кэширования исключения в качестве индикатора сбоя вместо повторного вызова метода. Предположим, что InvalidIsbnNotFoundException
генерируется, если структура ISBN недопустима. Это необратимый сбой (ни одну книгу нельзя будет найти с таким параметром). Ниже приводится кэширование исключения, благодаря которому последующие вызовы с тем же самым, недопустимым ISBN генерируют кэшированное исключение напрямую вместо повторного вызова метода:
@CacheResult(cacheName="books", exceptionCacheName="failures"
cachedExceptions = InvalidIsbnNotFoundException.class)
public Book findBook(ISBN isbn)
Активация средств поддержки JSR-107
Чтобы включить поддержку JSR-107 наряду с поддержкой декларативных аннотаций в Spring, не требуется делать что-то особенное. И аннотация @EnableCaching
, и элемент cache:annotation-driven
из XML автоматически активируют поддержку JCache, если в classpath присутствуют как API JSR-107, так и модуль spring-context-support
.