配置缓存存储
缓存抽象提供了多种存储集成选项。要使用它们,您需要声明一个合适的 CacheManager(一个控制和管理 Cache 实例的实体,可用于检索这些实例进行存储)。
基于 JDK ConcurrentMap 的缓存
基于 JDK 的 Cache 实现位于 org.springframework.cache.concurrent 包下。它允许您使用 ConcurrentHashMap 作为后端 Cache 存储。以下示例展示了如何配置两个缓存:
-
Java
-
Kotlin
-
Xml
@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;
}
@Bean
fun defaultCache(): ConcurrentMapCacheFactoryBean {
return ConcurrentMapCacheFactoryBean().apply {
setName("default")
}
}
@Bean
fun booksCache(): ConcurrentMapCacheFactoryBean {
return ConcurrentMapCacheFactoryBean().apply {
setName("books")
}
}
@Bean
fun cacheManager(defaultCache: ConcurrentMapCache, booksCache: ConcurrentMapCache): CacheManager {
return SimpleCacheManager().apply {
setCaches(setOf(defaultCache, booksCache))
}
}
<!-- simple cache manager -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" name="default"/>
<bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" name="books"/>
</set>
</property>
</bean>
上述代码片段使用 SimpleCacheManager 为两个嵌套的 ConcurrentMapCache 实例(名为 default 和 books)创建了一个 CacheManager。请注意,这些名称是直接为每个缓存配置的。
由于缓存是由应用程序创建的,它受应用程序生命周期限制,因此适用于基本用例、测试或简单应用程序。该缓存扩展性好,速度非常快,但不提供任何管理、持久化功能或逐出契约。
基于 Ehcache 的缓存
Ehcache 3.x 完全符合 JSR-107 规范,无需专门支持。有关详细信息,请参阅JSR-107 缓存。
Caffeine 缓存
Caffeine 是 Guava 缓存的 Java 8 重写,其实现位于 org.springframework.cache.caffeine 包中,并提供了对 Caffeine 多种功能的访问。
以下示例配置了一个按需创建缓存的 CacheManager:
-
Java
-
Kotlin
-
Xml
@Bean
CacheManager cacheManager() {
return new CaffeineCacheManager();
}
@Bean
fun cacheManager(): CacheManager {
return CaffeineCacheManager()
}
<bean id="cacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager"/>
您也可以显式提供要使用的缓存。在这种情况下,管理器只提供这些缓存。以下示例展示了如何实现:
-
Java
-
Kotlin
-
Xml
@Bean
CacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
cacheManager.setCacheNames(List.of("default", "books"));
return cacheManager;
}
@Bean
fun cacheManager(): CacheManager {
return CaffeineCacheManager("default", "books")
}
<bean id="cacheManager" class="org.springframework.cache.caffeine.CaffeineCacheManager">
<property name="cacheNames">
<set>
<value>default</value>
<value>books</value>
</set>
</property>
</bean>
Caffeine CacheManager 还支持自定义 Caffeine 和 CacheLoader。有关这些的更多信息,请参阅 Caffeine 文档。
基于 GemFire 的缓存
GemFire 是一个内存导向、磁盘支持、弹性伸缩、持续可用、活跃(内置基于模式的订阅通知)、全局复制的数据库,并提供功能齐全的边缘缓存。有关如何使用 GemFire 作为 CacheManager(以及更多)的详细信息,请参阅 Spring Data GemFire 参考文档。
JSR-107 缓存
Spring 的缓存抽象还可以使用符合 JSR-107 规范的缓存。JCache 实现位于 org.springframework.cache.jcache 包中。
同样,要使用它,您需要声明适当的 CacheManager。以下示例展示了如何实现:
-
Java
-
Kotlin
-
Xml
@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);
}
@Bean
fun jCacheManager(): javax.cache.CacheManager {
val cachingProvider = Caching.getCachingProvider()
return cachingProvider.getCacheManager()
}
@Bean
fun cacheManager(jCacheManager: javax.cache.CacheManager): org.springframework.cache.CacheManager {
return JCacheCacheManager(jCacheManager)
}
<bean id="cacheManager"
class="org.springframework.cache.jcache.JCacheCacheManager"
p:cache-manager-ref="jCacheManager"/>
<!-- JSR-107 cache manager setup -->
<bean id="jCacheManager" .../>
处理没有后端存储的缓存
有时,在切换环境或进行测试时,您可能声明了缓存,但没有配置实际的后端缓存。由于这是一种无效配置,运行时会抛出异常,因为缓存基础设施无法找到合适的存储。在这种情况下,您可以通过注入一个简单的虚拟缓存来避免每次都删除缓存声明(这可能很繁琐),该虚拟缓存不执行任何缓存——也就是说,它强制每次都调用缓存方法。以下示例展示了如何实现:
-
Java
-
Kotlin
-
Xml
@Bean
CacheManager cacheManager(CacheManager jdkCache, CacheManager gemfireCache) {
CompositeCacheManager cacheManager = new CompositeCacheManager();
cacheManager.setCacheManagers(List.of(jdkCache, gemfireCache));
cacheManager.setFallbackToNoOpCache(true);
return cacheManager;
}
@Bean
fun cacheManager(jdkCache: CacheManager, gemfireCache: CacheManager): CacheManager {
return CompositeCacheManager().apply {
setCacheManagers(listOf(jdkCache, gemfireCache))
setFallbackToNoOpCache(true)
}
}
<bean id="cacheManager" class="org.springframework.cache.support.CompositeCacheManager">
<property name="cacheManagers">
<list>
<ref bean="jdkCache"/>
<ref bean="gemfireCache"/>
</list>
</property>
<property name="fallbackToNoOpCache" value="true"/>
</bean>
上述代码中的 CompositeCacheManager 链式连接了多个 CacheManager 实例,并通过 fallbackToNoOpCache 标志为所有未由已配置的缓存管理器处理的定义添加了一个无操作缓存。也就是说,在 jdkCache 或 gemfireCache(在示例中早些配置)中未找到的每个缓存定义都将由无操作缓存处理,该缓存不存储任何信息,导致每次都调用目标方法。