Caching

Spring Framework 提供对透明地将缓存添加到应用程序的支持。在它的核心,这个抽象对方法应用了缓存,因此基于缓存中可用信息减少执行次数。缓存逻辑以透明的方式应用,没有任何对调用者的干扰。只要使用 @EnableCaching 注解启用缓存支持,Spring Boot 就能自动配置缓存基础设施。

The Spring Framework provides support for transparently adding caching to an application. At its core, the abstraction applies caching to methods, thus reducing the number of executions based on the information available in the cache. The caching logic is applied transparently, without any interference to the invoker. Spring Boot auto-configures the cache infrastructure as long as caching support is enabled by using the @EnableCaching annotation.

有关更多详细信息,请查阅 Spring Framework 参考的 {url-spring-framework-docs}/integration/cache.html[相关部分]。

Check the {url-spring-framework-docs}/integration/cache.html[relevant section] of the Spring Framework reference for more details.

简而言之,若要向服务的某个操作添加缓存,请对其方法添加相关注释,如下例所示:

In a nutshell, to add caching to an operation of your service add the relevant annotation to its method, as shown in the following example: include-code::MyMathService[]

本示例说明了在潜在成本高昂的操作上使用缓存的方法。在调用 computePiDecimal 之前,抽象将查找 piDecimals 缓存中与 i 参数匹配的条目。如果找到条目,缓存中的内容将立即返回给调用者,且该方法不会被调用。否则,将调用该方法,且在返回该值之前先对缓存进行更新。

This example demonstrates the use of caching on a potentially costly operation. Before invoking computePiDecimal, the abstraction looks for an entry in the piDecimals cache that matches the i argument. If an entry is found, the content in the cache is immediately returned to the caller, and the method is not invoked. Otherwise, the method is invoked, and the cache is updated before returning the value.

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

You can also use the standard JSR-107 (JCache) annotations (such as @CacheResult) transparently. However, we strongly advise you to not mix and match the Spring Cache and JCache annotations.

如果你没有添加任何特定的缓存库,Spring Boot 会自动配置一个使用内存中的并发映射的 simple provider。当需要使用缓存时(例如在前面的示例中的 piDecimals),此提供程序会为你创建缓存。简单的提供程序并不适合用于生产用途,但是非常适合于入门和确保你了解这些特性。当你决定要使用的缓存提供程序时,请务必仔细阅读其文档以了解如何配置你的应用程序使用的缓存。几乎所有提供程序都要求你明确配置应用程序中使用的每个缓存。有些提供程序提供自定义由 configprop:spring.cache.cache-names[] 属性定义的默认缓存的方法。

If you do not add any specific cache library, Spring Boot auto-configures a simple provider that uses concurrent maps in memory. When a cache is required (such as piDecimals in the preceding example), this provider creates it for you. The simple provider is not really recommended for production usage, but it is great for getting started and making sure that you understand the features. When you have made up your mind about the cache provider to use, please make sure to read its documentation to figure out how to configure the caches that your application uses. Nearly all providers require you to explicitly configure every cache that you use in the application. Some offer a way to customize the default caches defined by the configprop:spring.cache.cache-names[] property.

还可以透明地将数据从缓存中 {url-spring-framework-docs}/integration/cache/annotations.html#cache-annotations-put[更新] 或 {url-spring-framework-docs}/integration/cache/annotations.html#cache-annotations-evict[逐出]。

It is also possible to transparently {url-spring-framework-docs}/integration/cache/annotations.html#cache-annotations-put[update] or {url-spring-framework-docs}/integration/cache/annotations.html#cache-annotations-evict[evict] data from the cache.

Supported Cache Providers

缓存抽象不提供实际的存储,它依赖 org.springframework.cache.Cacheorg.springframework.cache.CacheManager 接口实现的抽象。

The cache abstraction does not provide an actual store and relies on abstraction materialized by the org.springframework.cache.Cache and org.springframework.cache.CacheManager interfaces.

如果你尚未定义 CacheManager 类型的 Bean 或名为 cacheResolverCacheResolver(请参见 {url-spring-framework-javadoc}/org/springframework/cache/annotation/CachingConfigurer.html[CachingConfigurer]),Spring Boot 将尝试按指示的顺序检测以下提供程序。

If you have not defined a bean of type CacheManager or a CacheResolver named cacheResolver (see {url-spring-framework-javadoc}/org/springframework/cache/annotation/CachingConfigurer.html[CachingConfigurer]), Spring Boot tries to detect the following providers (in the indicated order):

  1. Generic

  2. JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, and others)

  3. Hazelcast

  4. Infinispan

  5. Couchbase

  6. Redis

  7. Caffeine

  8. Cache2k

  9. Simple

此外,{url-spring-boot-for-apache-geode-site}[Spring Boot for Apache Geode] 提供 {url-spring-boot-for-apache-geode-docs}#geode-caching-provider[用于将 Apache Geode 用作缓存提供程序的自动配置]。

Additionally, {url-spring-boot-for-apache-geode-site}[Spring Boot for Apache Geode] provides {url-spring-boot-for-apache-geode-docs}#geode-caching-provider[auto-configuration for using Apache Geode as a cache provider].

如果 Spring Boot 自动配置 CacheManager,那么可以通过设置 configprop:spring.cache.type[] 属性来 force 特定的缓存提供程序。如果你需要在特定环境(例如测试)中 use no-op caches,请使用此属性。

If the CacheManager is auto-configured by Spring Boot, it is possible to force a particular cache provider by setting the configprop:spring.cache.type[] property. Use this property if you need to use no-op caches in certain environments (such as tests).

使用 spring-boot-starter-cache “Starter” 以快速添加基本的缓存依赖项。该 starter 会引入 spring-context-support。如果你手动添加依赖项,那么为了使用 JCache 或 Caffeine 支持,你必须包含 spring-context-support

Use the spring-boot-starter-cache “Starter” to quickly add basic caching dependencies. The starter brings in spring-context-support. If you add dependencies manually, you must include spring-context-support in order to use the JCache or Caffeine support.

如果 Spring Boot 自动配置 CacheManager,则可以在完全初始化之前通过公开一个实现了 CacheManagerCustomizer 接口的 Bean 来进一步调整其配置。以下示例设置一个标记来说 null 值不应传递到底层映射:

If the CacheManager is auto-configured by Spring Boot, you can further tune its configuration before it is fully initialized by exposing a bean that implements the CacheManagerCustomizer interface. The following example sets a flag to say that null values should not be passed down to the underlying map:

在前面的示例中,会预期自动配置 ConcurrentMapCacheManager。如果不是这种情况(或者是你提供了自己的配置,或者自动配置了其他缓存提供程序),那么将不会调用该定制器。你可以随意使用任意数量的定制器,还可以使用 @OrderOrdered 对其进行排序。

In the preceding example, an auto-configured ConcurrentMapCacheManager is expected. If that is not the case (either you provided your own config or a different cache provider was auto-configured), the customizer is not invoked at all. You can have as many customizers as you want, and you can also order them by using @Order or Ordered.

Generic

如果上下文定义 at leastorg.springframework.cache.Cache Bean,则使用通用缓存。将创建包含该类型的所有 Bean 的 CacheManager

Generic caching is used if the context defines at least one org.springframework.cache.Cache bean. A CacheManager wrapping all beans of that type is created.

JCache (JSR-107)

通过类路径中存在 javax.cache.spi.CachingProviderJCache 进行引导(也就是说,类路径中存在 JSR-107 兼容缓存库),而 JCacheCacheManagerspring-boot-starter-cache “Starter” 提供。现有多种兼容库可用,Spring Boot 为 Ehcache 3、Hazelcast 和 Infinispan 提供依赖项管理。也可以添加任何其他兼容库。

JCache is bootstrapped through the presence of a javax.cache.spi.CachingProvider on the classpath (that is, a JSR-107 compliant caching library exists on the classpath), and the JCacheCacheManager is provided by the spring-boot-starter-cache “Starter”. Various compliant libraries are available, and Spring Boot provides dependency management for Ehcache 3, Hazelcast, and Infinispan. Any other compliant library can be added as well.

可能有多个提供者,在这种情况下必须明确指定提供者。即使 JSR-107 标准没有强制执行定义配置文件位置的标准化方式,Spring Boot 也会尽力容纳带有实现细节的缓存设置,如下例所示:

It might happen that more than one provider is present, in which case the provider must be explicitly specified. Even if the JSR-107 standard does not enforce a standardized way to define the location of the configuration file, Spring Boot does its best to accommodate setting a cache with implementation details, as shown in the following example:

    # Only necessary if more than one provider is present
	spring:
	  cache:
	    jcache:
	      provider: "com.example.MyCachingProvider"
	      config: "classpath:example.xml"

当缓存库既提供本机实现又支持 JSR-107 时,Spring Boot 更喜欢使用 JSR-107 支持,以便在你切换到不同的 JSR-107 实现时可以使用相同的特性。

When a cache library offers both a native implementation and JSR-107 support, Spring Boot prefers the JSR-107 support, so that the same features are available if you switch to a different JSR-107 implementation.

Spring Boot 拥有 general support for Hazelcast。如果一个 HazelcastInstance 可用,它也会自动用于 CacheManager,除非指定了 configprop:spring.cache.jcache.config[] 属性。

Spring Boot has general support for Hazelcast. If a single HazelcastInstance is available, it is automatically reused for the CacheManager as well, unless the configprop:spring.cache.jcache.config[] property is specified.

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

There are two ways to customize the underlying javax.cache.cacheManager:

  • Caches can be created on startup by setting the configprop:spring.cache.cache-names[] property. If a custom javax.cache.configuration.Configuration bean is defined, it is used to customize them.

  • org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer beans are invoked with the reference of the CacheManager for full customization.

如果定义了标准 javax.cache.CacheManager Bean,则自动将其包装到抽象所需的一个 org.springframework.cache.CacheManager 实现中。未对其应用进一步自定义。

If a standard javax.cache.CacheManager bean is defined, it is wrapped automatically in an org.springframework.cache.CacheManager implementation that the abstraction expects. No further customization is applied to it.

Hazelcast

Spring Boot 拥有 general support for Hazelcast。如果已自动配置 HazelcastInstancecom.hazelcast:hazelcast-spring 在类路径上,则自动将其包装在 CacheManager 中。

Spring Boot has general support for Hazelcast. If a HazelcastInstance has been auto-configured and com.hazelcast:hazelcast-spring is on the classpath, it is automatically wrapped in a CacheManager.

Hazelcast 可用作 JCache 兼容缓存或 Spring CacheManager 兼容缓存。将 configprop:spring.cache.type[] 设置为 hazelcast 时,Spring Boot 将使用基于 CacheManager 的实现。如果想要使用 Hazelcast 作为 JCache 兼容缓存,请将 configprop:spring.cache.type[] 设置为 jcache。如果你有多个 JCache 兼容缓存提供者,并且想要强制使用 Hazelcast,则必须 explicitly set the JCache provider

Hazelcast can be used as a JCache compliant cache or as a Spring CacheManager compliant cache. When setting configprop:spring.cache.type[] to hazelcast, Spring Boot will use the CacheManager based implementation. If you want to use Hazelcast as a JCache compliant cache, set configprop:spring.cache.type[] to jcache. If you have multiple JCache compliant cache providers and want to force the use of Hazelcast, you have to explicitly set the JCache provider.

Infinispan

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

Infinispan has no default configuration file location, so it must be specified explicitly. Otherwise, the default bootstrap is used.

spring:
  cache:
    infinispan:
      config: "infinispan.xml"

可以通过设置 configprop:spring.cache.cache-names[] 属性在启动时创建缓存。如果定义了自定义 ConfigurationBuilder Bean,则使用它来自定义缓存。

Caches can be created on startup by setting the configprop:spring.cache.cache-names[] property. If a custom ConfigurationBuilder bean is defined, it is used to customize the caches.

为了兼容 Spring Boot 的 Jakarta EE 9 基线,必须使用 Infinispan 的 -jakarta 模块。对于具有 -jakarta 变体的每个模块,必须使用变体来代替标准模块。例如,必须分别使用 infinispan-core-jakartainfinispan-commons-jakarta 来代替 infinispan-coreinfinispan-commons

To be compatible with Spring Boot’s Jakarta EE 9 baseline, Infinispan’s -jakarta modules must be used. For every module with a -jakarta variant, the variant must be used in place of the standard module. For example, infinispan-core-jakarta and infinispan-commons-jakarta must be used in place of infinispan-core and infinispan-commons respectively.

Couchbase

如果 Spring Data Couchbase 可用且 Couchbase 是 configured,则会自动配置 CouchbaseCacheManager。可以通过设置 configprop:spring.cache.cache-names[] 属性创建附加缓存,可使用 spring.cache.couchbase.* 属性配置缓存默认值。例如,以下配置使用 10 分钟的条目 expiration 创建 cache1cache2 缓存:

If Spring Data Couchbase is available and Couchbase is configured, a CouchbaseCacheManager is auto-configured. It is possible to create additional caches on startup by setting the configprop:spring.cache.cache-names[] property and cache defaults can be configured by using spring.cache.couchbase.* properties. For instance, the following configuration creates cache1 and cache2 caches with an entry expiration of 10 minutes:

spring:
  cache:
    cache-names: "cache1,cache2"
    couchbase:
      expiration: "10m"

如果你需要对配置进行更多控制,可以考虑注册 CouchbaseCacheManagerBuilderCustomizer Bean。以下示例显示了一个自定义程序,它为 cache1cache2 配置了一个特定的条目过期时间:

If you need more control over the configuration, consider registering a CouchbaseCacheManagerBuilderCustomizer bean. The following example shows a customizer that configures a specific entry expiration for cache1 and cache2:

Redis

如果 Redis 可用且已配置,则会自动配置 RedisCacheManager。可以通过设置 configprop:spring.cache.cache-names[] 属性创建附加缓存,可使用 spring.cache.redis.* 属性配置缓存默认值。例如,以下配置使用 10 分钟的 time to live 创建 cache1cache2 缓存:

If Redis is available and configured, a RedisCacheManager is auto-configured. It is possible to create additional caches on startup by setting the configprop:spring.cache.cache-names[] property and cache defaults can be configured by using spring.cache.redis.* properties. For instance, the following configuration creates cache1 and cache2 caches with a time to live of 10 minutes:

spring:
  cache:
    cache-names: "cache1,cache2"
    redis:
      time-to-live: "10m"

默认情况下,会添加一个键前缀,以便如果两个单独的缓存使用相同的键,Redis 不会有重叠的键并且无法返回无效的值。如果你创建自己的 RedisCacheManager,我们强烈建议保持此设置处于启用状态。

By default, a key prefix is added so that, if two separate caches use the same key, Redis does not have overlapping keys and cannot return invalid values. We strongly recommend keeping this setting enabled if you create your own RedisCacheManager.

你可以通过添加自己的 RedisCacheConfiguration @Bean 来完全控制默认配置。如果你需要自定义默认序列化策略,这会很有用。

You can take full control of the default configuration by adding a RedisCacheConfiguration @Bean of your own. This can be useful if you need to customize the default serialization strategy.

如果你需要对配置进行更多控制,可以考虑注册 RedisCacheManagerBuilderCustomizer Bean。以下示例显示了一个自定义程序,它为 cache1cache2 配置了一个特定的生存时间:

If you need more control over the configuration, consider registering a RedisCacheManagerBuilderCustomizer bean. The following example shows a customizer that configures a specific time to live for cache1 and cache2:

Caffeine

Caffeine是Guava缓存的Java8重写,它取代了对Guava的支持。如果Caffeine存在,将`CaffeineCacheManager`(由`spring-boot-starter-cache`"`Starter`"提供)自动配置。可以通过设置configprop:spring.cache.cache-names[]属性来在启动时创建缓存,并且可以通过以下方式之一(按指示的顺序)进行自定义:

Caffeine is a Java 8 rewrite of Guava’s cache that supersedes support for Guava. If Caffeine is present, a CaffeineCacheManager (provided by the spring-boot-starter-cache “Starter”) is auto-configured. Caches can be created on startup by setting the configprop:spring.cache.cache-names[] property and can be customized by one of the following (in the indicated order):

  1. A cache spec defined by spring.cache.caffeine.spec

  2. A com.github.benmanes.caffeine.cache.CaffeineSpec bean is defined

  3. A com.github.benmanes.caffeine.cache.Caffeine bean is defined

例如,下列配置使用最大大小为500和_time to live_为10分钟的创建`cache1`和`cache2`缓存:

For instance, the following configuration creates cache1 and cache2 caches with a maximum size of 500 and a time to live of 10 minutes

spring:
  cache:
    cache-names: "cache1,cache2"
    caffeine:
      spec: "maximumSize=500,expireAfterAccess=600s"

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

If a com.github.benmanes.caffeine.cache.CacheLoader bean is defined, it is automatically associated to the CaffeineCacheManager. Since the CacheLoader is going to be associated with all caches managed by the cache manager, it must be defined as CacheLoader<Object, Object>. The auto-configuration ignores any other generic type.

Cache2k

Cache2k是一个内存缓存。如果存在Cache2k Spring集成,则自动配置`SpringCache2kCacheManager`。

Cache2k is an in-memory cache. If the Cache2k spring integration is present, a SpringCache2kCacheManager is auto-configured.

可以通过设置configprop:spring.cache.cache-names[]属性来在启动时创建缓存。可以使用`Cache2kBuilderCustomizer`bean自定义缓存默认值。以下示例显示了一个定制器,它将缓存的容量配置为200个条目,到期时间为5分钟:

Caches can be created on startup by setting the configprop:spring.cache.cache-names[] property. Cache defaults can be customized using a Cache2kBuilderCustomizer bean. The following example shows a customizer that configures the capacity of the cache to 200 entries, with an expiration of 5 minutes:

Simple

如果找不到任何其他提供程序,则配置使用`ConcurrentHashMap`作为缓存存储的简单实现。如果应用程序中不存在缓存库,则这是默认设置。默认情况下,会根据需要创建缓存,但是你可以通过设置`cache-names`属性来限制可用缓存的列表。例如,如果你只想保留`cache1`和`cache2`缓存,请按如下方式设置`cache-names`属性:

If none of the other providers can be found, a simple implementation using a ConcurrentHashMap as the cache store is configured. This is the default if no caching library is present in your application. By default, caches are created as needed, but you can restrict the list of available caches by setting the cache-names property. For instance, if you want only cache1 and cache2 caches, set the cache-names property as follows:

spring:
  cache:
    cache-names: "cache1,cache2"

如果你这样做并且你的应用程序使用了未列出的缓存,那么在需要缓存时(而不是在启动时)运行时会失败。这类似于在你使用未申报的缓存时,“实际”缓存提供程序的行为方式。

If you do so and your application uses a cache not listed, then it fails at runtime when the cache is needed, but not on startup. This is similar to the way the "real" cache providers behave if you use an undeclared cache.

None

当`@EnableCaching`存在于你的配置中时,也需要适当的缓存配置。如果你有自定义`CacheManager`,请考虑在单独的`@Configuration`类中对其进行定义,以便在必要时可以覆盖它。None使用无操作实现,这在测试中很有用,切片测试通过`@AutoConfigureCache`默认使用它。

When @EnableCaching is present in your configuration, a suitable cache configuration is expected as well. If you have a custom CacheManager, consider defining it in a separate @Configuration class so that you can override it if necessary. None uses a no-op implementation that is useful in tests, and slice tests use that by default via @AutoConfigureCache.

如果你需要在特定环境中使用无操作缓存,而不是自动配置的缓存管理器,请将缓存类型设置为`none`,如下例所示:

If you need to use a no-op cache rather than the auto-configured cache manager in a certain environment, set the cache type to none, as shown in the following example:

spring:
  cache:
    type: "none"