Spring框架支持透明地向应用程序添加缓存。从本质上讲,抽象将缓存应用于方法,从而根据缓存中可用的信息减少执行次数。缓存逻辑是透明应用的,不会对调用者造成任何干扰。只要通过@EnableCaching注释启用了缓存支持,Spring Boot就会自动配置缓存基础结构。

检查Spring Framework参考的相关部分以获取更多详细信息。

简而言之,要将缓存添加到服务的操作中,请在其方法中添加相关的注释,如以下示例所示:

  1. import org.springframework.cache.annotation.Cacheable;
  2. import org.springframework.stereotype.Component;
  3. @Component
  4. public class MathService {
  5. @Cacheable("piDecimals")
  6. public int computePiDecimal(int i) {
  7. // ...
  8. }
  9. }

本示例说明了在可能耗资巨大的操作上使用缓存的方法。在调用之前computePiDecimal,抽象将在piDecimals高速缓存中查找与i参数匹配的条目。如果找到条目,则高速缓存中的内容会立即返回给调用方,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。

您还可以@CacheResult透明地使用标准JSR-107(JCache)批注(例如)。但是,我们强烈建议您不要混合使用Spring Cache和JCache批注。

如果您不添加任何特定的缓存库,Spring Boot会自动配置一个使用内存中并发映射的简单提供程序。当需要缓存时(例如piDecimals前面的示例),此提供程序将为您创建它。实际上,不建议将简单的提供程序用于生产用途,但是它对于入门并确保您了解功能非常有用。确定要使用的缓存提供程序后,请确保阅读其文档,以了解如何配置应用程序使用的缓存。几乎所有提供程序都要求您显式配置在应用程序中使用的每个缓存。一些提供了一种自定义spring.cache.cache-names属性定义的默认缓存的方法。

也可以透明地更新或从缓存中逐出数据。

13.1 支持的缓存提供程序

缓存抽象不提供实际的存储,而是依赖于org.springframework.cache.Cacheorg.springframework.cache.CacheManager接口实现的抽象。
如果尚未定义类型CacheManagerCacheResolver名称的bean cacheResolver(请参阅参考资料CachingConfigurer),Spring Boot会尝试检测以下提供程序(按指示的顺序):

  1. 泛型
  2. JCache(JSR-107)(EhCache 3,Hazelcast,Infinispan等)
  3. EhCache 2.x
  4. 淡褐色
  5. Infinispan
  6. Couchbase
  7. 雷迪斯
  8. 咖啡因
  9. 简单 | | 也可以通过设置属性来强制特定的缓存提供程序spring.cache.type。如果您需要在某些环境(例如测试)中完全禁用缓存,请使用此属性。 | | :—-: | —- |
使用spring-boot-starter-cache“入门”可以快速添加基本缓存依赖项。起动器带进来spring-context-support。如果您手动添加依赖项,则必须包括spring-context-support才能使用JCache,EhCache 2.x或Caffeine支持。

如果CacheManagerSpring Boot自动配置了,您可以通过公开实现该CacheManagerCustomizer接口的bean,在完全初始化之前进一步调整其配置。下面的示例设置一个标志,指示null应将值向下传递到基础映射:

  1. @Bean
  2. public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
  3. return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
  4. @Override
  5. public void customize(ConcurrentMapCacheManager cacheManager) {
  6. cacheManager.setAllowNullValues(false);
  7. }
  8. };
  9. }
在前面的示例中,需要进行自动配置ConcurrentMapCacheManager。如果不是这种情况(您提供了自己的配置,或者自动配置了其他缓存提供程序),则根本不会调用定制程序。您可以根据需要拥有任意数量的定制程序,也可以使用@Order或对其进行排序Ordered

13.1.1 泛型

如果上下文定义了至少一个org.springframework.cache.Cachebean,则使用通用缓存。将CacheManager包装该类型的所有bean。

13.1.2 JCache(JSR-107)

JCache通过javax.cache.spi.CachingProvider类路径上的存在进行引导(即,类路径上存在符合JSR-107的缓存库),并且JCacheCacheManagerspring-boot-starter-cache“启动器”提供。提供了各种兼容的库,Spring Boot为Ehcache 3,Hazelcast和Infinispan提供了依赖管理。也可以添加任何其他兼容的库。
可能会出现多个提供者,在这种情况下,必须明确指定提供者。即使JSR-107标准没有强制采用标准化的方式来定义配置文件的位置,Spring Boot也会尽其最大努力来容纳具有实现细节的缓存,如以下示例所示:
物产
Yaml

  1. # Only necessary if more than one provider is present
  2. spring.cache.jcache.provider=com.acme.MyCachingProvider
  3. spring.cache.jcache.config=classpath:acme.xml
当缓存库同时提供本机实现和JSR-107支持时,Spring Boot会首选JSR-107支持,因此,如果切换到其他JSR-107实现,则可以使用相同的功能。
Spring Boot对Hazelcast具有常规支持。如果单个HazelcastInstance可用,则CacheManager除非spring.cache.jcache.config指定了该属性,否则也会自动将其重新使用。

有两种方法可以自定义基础javax.cache.cacheManager

  • 可以在启动时通过设置spring.cache.cache-names属性来创建缓存。如果定义了定制javax.cache.configuration.Configurationbean,则将其用于定制它们。
  • org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer使用的引用调用beanCacheManager进行完全定制。 | | 如果javax.cache.CacheManager定义了标准bean,则它将自动包装在org.springframework.cache.CacheManager抽象期望的实现中。不再对其应用定制。 | | :—-: | —- |

13.1.3 EhCache 2.x

如果ehcache.xml可以在类路径的根目录找到名为的文件,则使用EhCache2.x。如果找到EhCache 2.x,则使用“启动器”EhCacheCacheManager提供的spring-boot-starter-cache启动程序引导缓存管理器。也可以提供备用配置文件,如以下示例所示:
物产
Yaml

  1. spring.cache.ehcache.config=classpath:config/another-config.xml

13.1.4 淡褐色

Spring Boot对Hazelcast具有常规支持。如果HazelcastInstance已经自动配置了,则会自动将其包装在中CacheManager

13.1.5 Infinispan

Infinispan没有默认配置文件位置,因此必须明确指定它。否则,将使用默认的引导程序。
物产
Yaml

  1. spring.cache.infinispan.config=infinispan.xml

可以在启动时通过设置spring.cache.cache-names属性来创建缓存。如果定义了定制ConfigurationBuilderbean,则将其用于定制高速缓存。

Spring Boot对Infinispan的支持仅限于嵌入式模式,并且非常基础。如果您需要更多选择,则应该使用官方的Infinispan Spring Boot启动程序。有关更多详细信息,请参见Infinispan的文档

13.1.6 Couchbase

如果Spring Data Couchbase可用并且已配置Couchbase ,CouchbaseCacheManager则会自动配置a。可以通过设置spring.cache.cache-names属性在启动时创建其他缓存,并且可以使用spring.cache.couchbase.*属性配置缓存默认值。例如,以下配置创建cache1cache2缓存条目的到期时间为10分钟:
物产
Yaml

  1. spring.cache.cache-names=cache1,cache2
  2. spring.cache.couchbase.expiration=10m

如果需要对配置进行更多控制,请考虑注册CouchbaseCacheManagerBuilderCustomizerBean。以下示例显示了一个定制程序,它为cache1和配置特定的条目到期时间cache2

  1. @Bean
  2. public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() {
  3. return (builder) -> builder
  4. .withCacheConfiguration("cache1",
  5. CouchbaseCacheConfiguration.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
  6. .withCacheConfiguration("cache2",
  7. CouchbaseCacheConfiguration.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));
  8. }

13.1.7 Redis

如果Redis可用并已配置,RedisCacheManager则会自动配置a。可以通过设置spring.cache.cache-names属性在启动时创建其他缓存,并且可以使用spring.cache.redis.*属性配置缓存默认值。例如,以下配置创建cache1cache2缓存的_生存时间为_10分钟:
物产
Yaml

  1. spring.cache.cache-names=cache1,cache2
  2. spring.cache.redis.time-to-live=10m
默认情况下,会添加密钥前缀,这样,如果两个单独的缓存使用相同的密钥,则Redis不会有重叠的密钥,也不会返回无效值。如果您创建自己的,我们强烈建议将此设置保持启用状态RedisCacheManager
您可以通过添加RedisCacheConfiguration @Bean自己的a来完全控制默认配置。如果您要自定义默认的序列化策略,这将很有用。

如果需要对配置进行更多控制,请考虑注册RedisCacheManagerBuilderCustomizerBean。以下示例显示了一个定制程序,它为cache1and配置生存时间cache2

  1. @Bean
  2. public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
  3. return (builder) -> builder
  4. .withCacheConfiguration("cache1",
  5. RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
  6. .withCacheConfiguration("cache2",
  7. RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));
  8. }

13.1.8 Caffeine

Caffeine是对Guava缓存的Java 8重写,取代了对Guava的支持。如果存在咖啡因,CaffeineCacheManager则将spring-boot-starter-cache自动配置(由“入门”提供)。缓存可以在启动时通过设置spring.cache.cache-names属性来创建,并且可以通过以下方式之一(按指示的顺序)进行自定义:

  1. 缓存规范由 spring.cache.caffeine.spec
  2. com.github.benmanes.caffeine.cache.CaffeineSpec定义了一个bean
  3. com.github.benmanes.caffeine.cache.Caffeine定义了一个bean

例如,以下配置创建cache1cache2缓存的最大大小为500,_生存时间为_10分钟
物产
Yaml

  1. spring.cache.cache-names=cache1,cache2
  2. spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s

如果com.github.benmanes.caffeine.cache.CacheLoader定义了bean,它将自动与关联CaffeineCacheManager。由于CacheLoader将会与缓存管理器管理的所有缓存相关联,因此必须将其定义为CacheLoader<Object, Object>。自动配置将忽略任何其他通用类型。

13.1.9 简单

如果找不到其他提供者,ConcurrentHashMap则配置使用作为缓存存储的简单实现。如果您的应用程序中没有缓存库,则这是默认设置。默认情况下,将根据需要创建缓存,但是您可以通过设置cache-names属性来限制可用缓存的列表。例如,如果只需要cache1cache2缓存,则按cache-names如下所示设置属性:
物产
Yaml

  1. spring.cache.cache-names=cache1,cache2

如果这样做,并且您的应用程序使用未列出的缓存,则需要缓存时,它将在运行时失败,但不会在启动时失败。这类似于使用未声明的缓存时“实际”缓存提供程序的行为。

13.1.10 没有

@EnableCaching配置中存在时,也将期望使用合适的缓存配置。如果需要在某些环境中完全禁用缓存,请强制缓存类型none使用无操作实现,如以下示例所示:
物产
Yaml

  1. spring.cache.type=none