JCache (JSR-107) Annotations
自 4.1 版本以来,Spring 的缓存抽象完全支持 JCache 标准 (JSR-107) 注解:@CacheResult
、@CachePut
、@CacheRemove
和 @CacheRemoveAll
,以及 @CacheDefaults
、@CacheKey
和 @CacheValue
伙伴。即使不将缓存存储迁移到 JSR-107,您也可以使用这些注释。内部实现使用 Spring 的缓存抽象,并提供与规范兼容的默认 CacheResolver
和 KeyGenerator
实现。换句话说,如果您已经在使用 Spring 的缓存抽象,则可以在不更改缓存存储(或配置)的情况下切换到这些标准注释。
Since version 4.1, Spring’s caching abstraction fully supports the JCache standard
(JSR-107) annotations: @CacheResult
, @CachePut
, @CacheRemove
, and @CacheRemoveAll
as well as the @CacheDefaults
, @CacheKey
, and @CacheValue
companions.
You can use these annotations even without migrating your cache store to JSR-107.
The internal implementation uses Spring’s caching abstraction and provides default
CacheResolver
and KeyGenerator
implementations that are compliant with the
specification. In other words, if you are already using Spring’s caching abstraction,
you can switch to these standard annotations without changing your cache storage
(or configuration, for that matter).
Feature Summary
对于熟悉 Spring 的缓存注释的人来说,下表描述了 Spring 注释与其 JSR-107 对应项之间的主要差异:
For those who are familiar with Spring’s caching annotations, the following table describes the main differences between the Spring annotations and their JSR-107 counterparts:
Spring | JSR-107 | Remark |
---|---|---|
|
|
Fairly similar. |
|
|
While Spring updates the cache with the result of the method invocation, JCache
requires that it be passed it as an argument that is annotated with |
|
|
Fairly similar. |
|
|
See |
|
|
Lets you configure the same concepts, in a similar fashion. |
JCache 有 javax.cache.annotation.CacheResolver
的概念,它与 Spring 的 CacheResolver
接口相同,只是 JCache 只支持一个缓存。默认情况下,一个简单的实现基于注释中声明的名称检索要使用的缓存。需要注意的是,如果注释中未指定缓存名称,则会自动生成一个默认名称。有关详细信息,请参阅 @CacheResult#cacheName()
的 Java 文档。
JCache has the notion of javax.cache.annotation.CacheResolver
, which is identical
to the Spring’s CacheResolver
interface, except that JCache supports only a single
cache. By default, a simple implementation retrieves the cache to use based on the
name declared on the annotation. It should be noted that, if no cache name is
specified on the annotation, a default is automatically generated. See the javadoc
of @CacheResult#cacheName()
for more information.
CacheResolver
实例由 CacheResolverFactory
检索。可以为每个缓存操作自定义工厂,如下例所示:
CacheResolver
instances are retrieved by a CacheResolverFactory
. It is possible
to customize the factory for each cache operation, as the following example shows:
@CacheResult(cacheNames="books", cacheResolverFactory=MyCacheResolverFactory.class) 1
public Book findBook(ISBN isbn)
1 | Customizing the factory for this operation. |
对于所有引用的类,Spring 尝试查找给定类型的 Bean。如果存在多个匹配项,则会创建一个新实例,并且可以使用常规 Bean 生命周期回调,例如依赖注入。 |
For all referenced classes, Spring tries to locate a bean with the given type. If more than one match exists, a new instance is created and can use the regular bean lifecycle callbacks, such as dependency injection. |
键由 javax.cache.annotation.CacheKeyGenerator
生成,其用途与 Spring 的 KeyGenerator
相同。默认情况下,所有方法参数都将被考虑在内,除非使用 @CacheKey
标记至少一个参数。这与 Spring 的 custom key generation declaration 类似。例如,以下操作是相同的,一个使用 Spring 抽象,另一个使用 JCache:
Keys are generated by a javax.cache.annotation.CacheKeyGenerator
that serves the
same purpose as Spring’s KeyGenerator
. By default, all method arguments are taken
into account, unless at least one parameter is annotated with @CacheKey
. This is
similar to Spring’s custom key generation declaration
. For instance, the following are identical operations, one using
Spring’s abstraction and the other using 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
。
You can also specify the CacheKeyResolver
on the operation, similar to how you can
specify the CacheResolverFactory
.
JCache 可以管理注释方法抛出的异常。这可以阻止更新缓存,但也可以将异常缓存为失败指标,而不是再次调用该方法。假设在 ISBN 结构无效时抛出 InvalidIsbnNotFoundException
。这是一个永久性故障(永远无法使用这样的参数检索到书)。以下代码缓存该异常,以便使用相同的无效 ISBN 进行的进一步调用直接抛出缓存异常,而不是再次调用该方法:
JCache can manage exceptions thrown by annotated methods. This can prevent an update of
the cache, but it can also cache the exception as an indicator of the failure instead of
calling the method again. Assume that InvalidIsbnNotFoundException
is thrown if the
structure of the ISBN is invalid. This is a permanent failure (no book could ever be
retrieved with such a parameter). The following caches the exception so that further
calls with the same, invalid, ISBN throw the cached exception directly instead of
invoking the method again:
@CacheResult(cacheName="books", exceptionCacheName="failures"
cachedExceptions = InvalidIsbnNotFoundException.class)
public Book findBook(ISBN isbn)
Enabling JSR-107 Support
您无需执行任何特定操作即可启用 JSR-107 支持以及 Spring 的声明性注释支持。如果 JSR-107 API 和 spring-context-support
模块同时存在于类路径中,则 @EnableCaching
和 cache:annotation-driven
XML 元素都会自动启用 JSR-107 支持。
You do not need to do anything specific to enable the JSR-107 support alongside Spring’s
declarative annotation support. Both @EnableCaching
and the cache:annotation-driven
XML element automatically enable the JCache support if both the JSR-107 API and the
spring-context-support
module are present in the classpath.
根据使用场景,基本由你决定。你甚至可以通过在一些服务上使用 JSR-107 API,并在其他服务上使用 Spring 自己的注释来混合和匹配服务。但是,如果这些服务影响同一缓存,则应使用一致且相同的密钥生成实现。 |
Depending on your use case, the choice is basically yours. You can even mix and match services by using the JSR-107 API on some and using Spring’s own annotations on others. However, if these services impact the same caches, you should use a consistent and identical key generation implementation. |