JCache (JSR-107) 注解

从 4.1 版本开始,Spring 的缓存抽象完全支持 JCache 标准 (JSR-107) 注解:@CacheResult@CachePut@CacheRemove@CacheRemoveAll,以及配套的 @CacheDefaults@CacheKey@CacheValue。即使不将缓存存储迁移到 JSR-107,你也可以使用这些注解。内部实现使用 Spring 的缓存抽象,并提供符合规范的默认 CacheResolverKeyGenerator 实现。换句话说,如果你已经在使用 Spring 的缓存抽象,你可以切换到这些标准注解,而无需更改你的缓存存储(或配置)。

功能摘要

对于熟悉 Spring 缓存注解的用户,下表描述了 Spring 注解与 JSR-107 对应项之间的主要区别。

表 1. Spring 与 JSR-107 缓存注解
Spring JSR-107 备注

@Cacheable

@CacheResult

非常相似。@CacheResult 可以缓存特定异常,并强制执行方法,而不管缓存的内容如何。

@CachePut

@CachePut

虽然 Spring 用方法调用的结果更新缓存,但 JCache 要求将其作为用 @CacheValue 注解的参数传递。由于此差异,JCache 允许在实际方法调用之前或之后更新缓存。

@CacheEvict

@CacheRemove

非常相似。@CacheRemove 支持在方法调用导致异常时进行有条件的逐出。

@CacheEvict(allEntries=true)

@CacheRemoveAll

请参阅 @CacheRemove

@CacheConfig

@CacheDefaults

以类似的方式配置相同的概念。

JCache 具有 javax.cache.annotation.CacheResolver 的概念,它与 Spring 的 CacheResolver 接口相同,只是 JCache 仅支持单个缓存。默认情况下,一个简单的实现根据注解上声明的名称检索要使用的缓存。值得注意的是,如果注解上没有指定缓存名称,则会自动生成一个默认名称。有关更多信息,请参阅 @CacheResult#cacheName() 的 Javadoc。

CacheResolver 实例由 CacheResolverFactory 检索。可以为每个缓存操作自定义工厂,如以下示例所示。

@CacheResult(cacheNames="books", cacheResolverFactory=MyCacheResolverFactory.class) (1)
public Book findBook(ISBN isbn)
1 为该操作自定义工厂。
对于所有引用的类,Spring 都会尝试查找具有给定类型的 bean。如果存在多个匹配项,则会创建一个新实例,并且可以使用常规的 bean 生命周期回调,例如依赖注入。

键由 javax.cache.annotation.CacheKeyGenerator 生成,其目的与 Spring 的 KeyGenerator 相同。默认情况下,所有方法参数都将被考虑,除非至少一个参数被 @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 可以管理由注解方法抛出的异常。这可以防止缓存更新,但也可以将异常缓存作为失败的指示,而不是再次调用方法。假设如果 ISBN 结构无效,则抛出 InvalidIsbnNotFoundException。这是一个永久性故障(使用此类参数永远无法检索到书籍)。以下内容会缓存异常,因此使用相同且无效的 ISBN 进行后续调用将直接抛出缓存的异常,而不是再次调用该方法。

@CacheResult(cacheName="books", exceptionCacheName="failures"
			cachedExceptions = InvalidIsbnNotFoundException.class)
public Book findBook(ISBN isbn)

启用 JSR-107 支持

你不需要执行任何特定操作来启用 JSR-107 支持以及 Spring 的声明式注解支持。如果 JSR-107 API 和 spring-context-support 模块都存在于类路径中,则 @EnableCachingcache:annotation-driven XML 元素都会自动启用 JCache 支持。

根据你的用例,选择权基本上在你手中。你甚至可以通过在某些服务上使用 JSR-107 API,而在其他服务上使用 Spring 自己的注解来混合搭配服务。但是,如果这些服务影响相同的缓存,则应使用一致且相同的键生成实现。
© . This site is unofficial and not affiliated with VMware.