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支持

您无需执行任何特定操作即可在Spring的声明性注解支持旁边启用JSR-107支持。如果JSR-107 API和spring-context-support模块同时存在于类路径中,@EnableCachingcache:annotation-driven XML元素将自动启用JCache支持。

根据您的用例,选择基本上取决于您。您甚至可以通过在某些服务上使用JSR-107 API并在其他服务上使用Spring自己的注解来混合和匹配服务。但是,如果这些服务影响相同的缓存,您应该使用一致且相同的键生成实现。