跳到主要内容

配置缓存存储

ChatGPT-4o 中英对照 Configuring the Cache Storage

缓存抽象提供了多种存储集成选项。要使用它们,你需要声明一个合适的 CacheManager(一个控制和管理 Cache 实例的实体,可以用于检索这些实例以进行存储)。

基于 JDK ConcurrentMap 的缓存

基于 JDK 的 Cache 实现在 org.springframework.cache.concurrent 包下。它允许你使用 ConcurrentHashMap 作为后备 Cache 存储。下面的示例展示了如何配置两个缓存:

@Bean
ConcurrentMapCacheFactoryBean defaultCache() {
ConcurrentMapCacheFactoryBean cache = new ConcurrentMapCacheFactoryBean();
cache.setName("default");
return cache;
}

@Bean
ConcurrentMapCacheFactoryBean booksCache() {
ConcurrentMapCacheFactoryBean cache = new ConcurrentMapCacheFactoryBean();
cache.setName("books");
return cache;
}

@Bean
CacheManager cacheManager(ConcurrentMapCache defaultCache, ConcurrentMapCache booksCache) {

SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.setCaches(Set.of(defaultCache, booksCache));
return cacheManager;
}
java

前面的代码片段使用 SimpleCacheManager 创建一个 CacheManager,用于两个嵌套的 ConcurrentMapCache 实例,分别命名为 defaultbooks。注意,名称是直接为每个缓存配置的。

由于缓存是由应用程序创建的,因此它与应用程序的生命周期绑定,这使其适合基本用例、测试或简单应用程序。缓存具有良好的可扩展性且速度非常快,但它不提供任何管理、持久化功能或驱逐策略。

基于 Ehcache 的缓存

Ehcache 3.x 完全符合 JSR-107 标准,不需要专门的支持。详情请参见 JSR-107 缓存

Caffeine 缓存

Caffeine 是 Guava 缓存的 Java 8 重写版,其实现位于 org.springframework.cache.caffeine 包中,并提供对 Caffeine 的多个功能的访问。

下面的示例配置了一个 CacheManager,该管理器按需创建缓存:

@Bean
CacheManager cacheManager() {
return new CaffeineCacheManager();
}
java

您也可以显式地提供要使用的缓存。在这种情况下,只有这些缓存由管理器提供。以下示例展示了如何做到这一点:

@Bean
CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCacheNames(List.of("default", "books"));
return cacheManager;
}
java

CaffeineCacheManager 还支持自定义的 CaffeineCacheLoader。有关这些的更多信息,请参阅 Caffeine 文档

基于 GemFire 的缓存

GemFire 是一个面向内存、磁盘支持、弹性可扩展、持续可用、主动(具有内置的基于模式的订阅通知)、全球复制的数据库,并提供功能齐全的边缘缓存。有关如何将 GemFire 用作 CacheManager(以及更多)的信息,请参阅 Spring Data GemFire 参考文档

JSR-107 缓存

Spring 的缓存抽象也可以使用符合 JSR-107 的缓存。JCache 实现位于 org.springframework.cache.jcache 包中。

同样,要使用它,你需要声明适当的 CacheManager。以下示例展示了如何做到这一点:

@Bean
javax.cache.CacheManager jCacheManager() {
CachingProvider cachingProvider = Caching.getCachingProvider();
return cachingProvider.getCacheManager();
}

@Bean
org.springframework.cache.CacheManager cacheManager(javax.cache.CacheManager jCacheManager) {
return new JCacheCacheManager(jCacheManager);
}
java

处理没有后备存储的缓存

有时,在切换环境或进行测试时,您可能会有缓存声明,但没有配置实际的缓存支持。由于这是一个无效的配置,运行时会抛出异常,因为缓存基础设施无法找到合适的存储。在这种情况下,与其删除缓存声明(这可能会很繁琐),您可以连接一个简单的虚拟缓存,它不执行任何缓存操作——也就是说,它强制每次都调用缓存的方法。以下示例展示了如何实现:

@Bean
CacheManager cacheManager(CacheManager jdkCache, CacheManager gemfireCache) {
CompositeCacheManager cacheManager = new CompositeCacheManager();
cacheManager.setCacheManagers(List.of(jdkCache, gemfireCache));
cacheManager.setFallbackToNoOpCache(true);
return cacheManager;
}
java

前面的 CompositeCacheManager 链接了多个 CacheManager 实例,并通过 fallbackToNoOpCache 标志,为所有未被配置的缓存管理器处理的定义添加了一个无操作缓存。也就是说,任何在 jdkCachegemfireCache(在示例中较早配置)中找不到的缓存定义都由无操作缓存处理,该缓存不存储任何信息,导致目标方法每次都被调用。