JCache (JSR-107) 注解
自 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 要求将其作为用 `@CacheValue` 注解的参数传递。由于这种差异,JCache 允许在实际方法调用之前或之后更新缓存。 |
|
|
非常相似。当方法调用导致异常时,`@CacheRemove` 支持条件性驱逐。 |
|
|
参见 `@CacheRemove`。 |
|
|
允许你以类似的方式配置相同的概念。 |
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)