JCache(JSR-107)注解
从 4.1 版开始,Spring 的缓存抽象完全支持 JCache 标准注解:@CacheResult
、@CachePut
、@CacheRemove
和 @CacheRemoveAll
以及 @CacheDefaults
、@CacheKey
和@CacheValue
。即使不将缓存存储库迁移到 JSR-107,也可以使用这些注解,内部实现使用 Spring 的缓存抽象,并提供符合规范的默认 CacheResolver
和KeyGenerator
实现。换句话说,如果你已经在使用 Spring 的缓存抽象,则可以切换到这些标准注解,而无需更改缓存存储(或配置,就此而言)。
特性摘要
对于那些熟悉 Spring 的缓存注解的,下表描述了 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)
public Book findBook(ISBN isbn)
对于所有引用的类,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 支持
除了 Spring 的声明性注解支持之外,你无需执行任何特定的操作来启用 JSR-107 支持,如果 JSR-107 API 和 spring-context-support
模块都存在于类路径中,则 @EnableCaching
和cache:annotation-driven
元素都会自动启用 JCache 支持。
根据你的用例,选择基本上是你自己的,你甚至可以在某些服务上使用 JSR-107 API 并在其他服务上使用 Spring 自己的注解来混合和匹配服务。但是,如果这些服务影响相同的缓存,则应使用一致且相同的键生成实现。