领先一步
VMware 提供培训和认证,助您加速进步。
了解更多这篇文章是我的先前 关于 JSR-107 的文章 的后续。添加 JSR-107 支持使我们有机会回顾我们自己的实现,并看看两者如何和谐共存。Spring 4.1 还包含社区报告的一系列改进。
我也很高兴地宣布,一本专门针对缓存抽象的新的入门指南已经发布,请查看 使用 Spring 缓存数据!
我们在 JSR-107 中发现的一个最好的特性是能够在运行时解析要使用的缓存,这是基于实际的方法执行的。到目前为止,我们自己的支持依赖于在注解(或切面定义)级别指定缓存名称。社区提出了几个问题,报告当使用多个 CacheManager
时,需要能够自定义那些名称解析到的管理器。
我们最终所做的是创建了一个类似的 CacheResolver
抽象,以提供最灵活的选项。您可能已经猜到,默认实现接受一个 CacheManager
并根据提供的缓存名称解析要使用的缓存。由于不再需要这些名称,Spring 4.1 允许您编写如下代码
@Cacheable
public Book findBook(ISBN isbn) {...}
当然,您必须指定自己的 CacheResolver
,它知道如何处理这个特定的调用,或者您需要以不同的方式提供要使用的缓存(继续阅读)。
正如注解的 value
属性不再是必需的一样,只要设置了 CacheResolver
,就可以省略 CacheManager
。如果您以不同的方式管理 Cache
实例,您的 CacheResolver
实现可能根本不依赖于 CacheManager
。
社区还报告称,他们希望能够以更细粒度的方式控制缓存行为。Spring 4.1 允许您为每个操作指定要使用的 CacheResolver
(或 CacheManager
)和 KeyGenerator
。
例如,以下代码将一个自定义的 KeyGenerator
应用于那个特定的操作
@Cacheable(value="book", keyGenerator="myKeyGenerator")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
这会查找一个名称为 myKeyGenerator
的 KeyGenerator
bean。CacheManager 和缓存解析器实例也可以以类似的方式设置。
另一个社区反馈是能够在方法级别共享这些自定义设置,而无需启用任何默认缓存行为。引入 @CacheConfig
,它在类级别提供相同的自定义设置,即缓存名称、CacheResolver
(或 CacheManager
)和 KeyGenerator
。
@CacheConfig(cacheNames="book", keyGenerator="myKeyGenerator")
public class BookRepository {
@Cacheable
public Book findBook(ISBN isbn) {...}
public Book thisIsNotCached(String someArg) {...}
}
我们实现 JSR-107 支持时的主要目标之一是利用我们自己抽象中已有的东西,以便现有应用程序可以非常顺利地过渡。JCache 支持实际上在内部使用了 Spring 的缓存抽象,这使您可以使用标准注解重用您现有的缓存基础设施。当您指定一个 JSR-107 自定义组件,例如 javax.cache.annotation.CacheResolver
或 javax.cache.annotation.CacheKeyGenerator
时,我们会使用适配器将其通过我们的抽象进行路由。
具体来说,这意味着您可以保留您现有的基础设施并选择您想要的任何机制。例如,您可以有一个 ConcurrentMapCacheManager
,它在幕后使用 ConcurrentHashMap
并配合标准的 JSR-107 注解。
如果您想尝试一下,请查看这个 使用 JCache 而非 Spring 注解的指南分支(commit 32fea97 展示了具体改动)。
Spring 4.1 将于今年夏天发布,它将对其缓存抽象进行重大增强;添加对 JSR-107 的支持帮助我们进一步改进了这一点。本文未涵盖其他一些小的增强功能,例如更好的异常处理以及 Cache
接口上方便的 putIfAbsent
方法。
和往常一样,我们欢迎社区反馈,请尝试这些功能,并告知我们您是否遇到任何问题。