缓存

Spring 框架支持向应用程序透明添加缓存。 其核心是将缓存应用于方法,从而根据缓存中可用的信息减少执行次数。 缓存逻辑是透明应用的,不会干扰调用器。 只要启用缓存支持,Spring Boot 会通过使用@EnableCaching注解。spring-doc.cadn.net.cn

详情请查阅春季框架参考文献中的相关部分

简而言之,要为服务的某个作添加缓存,请在其方法中添加相应注释,如下示例所示:spring-doc.cadn.net.cn

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class MyMathService {

	@Cacheable("piDecimals")
	public int computePiDecimal(int precision) {
		...
	}

}
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Component

@Component
class MyMathService {

	@Cacheable("piDecimals")
	fun computePiDecimal(precision: Int): Int {
		...
	}

}

这个例子展示了缓存在可能代价高昂的作中被使用。 在召唤之前计算十进制,抽象寻找圆进制精度论点。 如果找到条目,缓存中的内容会立即返回给调用者,且该方法不会被调用。 否则,方法会被调用,缓存会在返回值之前更新。spring-doc.cadn.net.cn

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

如果你没有添加任何特定的缓存库,Spring Boot 会自动配置一个简单的提供者,使用内存中的并发映射。 当需要缓存时(例如圆进制在上述例子中,这个提供商为你创建了它。 简单提供商并不推荐用于生产环境,但它非常适合入门并确保你了解功能。 当你决定使用哪个缓存提供商时,请务必阅读其文档,了解如何配置你的应用所使用的缓存。 几乎所有提供商都要求你明确配置应用中使用的每个缓存。 有些网站提供自定义由spring.cache.cache-names财产。spring-doc.cadn.net.cn

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

支持的缓存提供者

缓存抽象不提供实际存储,依赖于通过缓存缓存管理器接口。spring-doc.cadn.net.cn

如果你没有定义 的 bean 类型缓存管理器或者缓存解析器缓存解析器(参见缓存配置器),Spring Boot 尝试检测以下提供者(按指示顺序):spring-doc.cadn.net.cn

如果缓存管理器由 Spring Boot 自动配置,可以通过设置spring.cache.type财产。 如果你需要在某些环境(比如测试)中使用无作缓存,可以使用这个属性。
使用该Spring Boot启动缓存快速添加基础缓存依赖的起始工具。 发令员送回spring-context-support. 如果你手动添加依赖,必须包含spring-context-support以便使用 JCache 或 Caffeine 支持。

如果缓存管理器由 Spring Boot 自动配置,你可以通过暴露一个实现缓存管理器定制器接口。 以下示例设置了一个标志,表示值不应传递到底层映射:spring-doc.cadn.net.cn

import org.springframework.boot.cache.autoconfigure.CacheManagerCustomizer;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyCacheManagerConfiguration {

	@Bean
	public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
		return (cacheManager) -> cacheManager.setAllowNullValues(false);
	}

}
import org.springframework.boot.cache.autoconfigure.CacheManagerCustomizer
import org.springframework.cache.concurrent.ConcurrentMapCacheManager
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyCacheManagerConfiguration {

	@Bean
	fun cacheManagerCustomizer(): CacheManagerCustomizer<ConcurrentMapCacheManager> {
		return CacheManagerCustomizer { cacheManager ->
			cacheManager.isAllowNullValues = false
		}
	}

}
在前面的例子中,自动配置ConcurrentMapCacheManager这是预期中的。 如果不是这样(要么你自己提供了配置,要么是自动配置了不同的缓存提供商),那么自定义器根本不会被调用。 你可以拥有任意数量的自定义器,也可以通过以下方式订购@Order命令.

通用

如果上下文定义至少一个,则使用泛型缓存缓存豆。 一个缓存管理器所有这种类型的豆子都会被包裹起来。spring-doc.cadn.net.cn

JCache(JSR-107)

JCache 是通过缓存提供商在类路径上(即在类路径上存在符合JSR-107标准的缓存库),以及JCacheCacheManagerSpring Boot启动缓存起动机。 提供多种兼容库,Spring Boot 为 Ehcache 3、Hazelcast 和 Infinispan 提供依赖管理。 还可以添加任何其他合规的库。spring-doc.cadn.net.cn

可能出现多个提供者的情况,此时必须明确指定提供者。 即使 JSR-107 标准没有强制要求标准化的方式来定义配置文件的位置,Spring Boot 也尽力支持设置带有实现细节的缓存,如下示例所示:spring-doc.cadn.net.cn

spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.xml
# 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 实现,也能使用相同的功能。
Spring Boot 对 Hazelcast 有一般支持。 如果是单曲Hazelcast实例是可用的,它会自动被重新用于缓存管理器此外,除非spring.cache.jcache.config属性被指定。

有两种方式可以自定义底层缓存管理器:spring-doc.cadn.net.cn

如果是标准缓存管理器豆子是定义的,它会自动包裹在缓存管理器实现了抽象所期望的。 没有进一步的自定义功能。

Hazelcast

Spring Boot 对 Hazelcast 有一般支持。 如果Hazelcast实例已被自动配置com.hazelcast:Hazelcast-Spring在类路径上,它会自动被包裹在缓存管理器.spring-doc.cadn.net.cn

Hazelcast 可以作为符合 JCache 的缓存或 Spring 使用。缓存管理器合规缓存。 设置时spring.cache.typeHazelcastSpring靴将使用缓存管理器基于实施。 如果你想用Hazelcast作为符合JCache的缓存,设置spring.cache.typejcache. 如果你有多个符合 JCache 的缓存提供商,并且想强制使用 Hazelcast,你必须明确设置 JCache 提供商。

无限展

Infinispan 没有默认配置文件位置,因此必须明确指定。 否则,使用默认的引导程序。spring-doc.cadn.net.cn

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

通过设置spring.cache.cache-names财产。 如果是习俗配置构建器BEAN 是定义的,用于自定义缓存。spring-doc.cadn.net.cn

为了兼容Spring Boot的Jakarta EE 9基础版,Infinispan的-雅加达必须使用模块。 对于每个具有 的模-雅加达变体必须用来替代标准模块。 例如无限扩展-核心-雅加达无限空间-公地-雅加达必须用来代替无限扩展核心无限空间公地分别。spring-doc.cadn.net.cn

沙发底座

如果Spring Data Couchbase可用且Couchbase已配置,则CouchbaseCacheManager是自动配置的。 启动时可以通过设置spring.cache.cache-names属性和缓存默认值可以通过以下方式配置spring.cache.couchbase.*性能。 例如,以下配置为缓存1缓存2条目截止时间为10分钟的缓存:spring-doc.cadn.net.cn

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

如果你需要对配置有更多控制,可以考虑注册一个CouchbaseCacheManagerBuilderCustomizer豆。 以下示例展示了一个自定义器,它配置了特定的条目到期时间缓存1缓存2:spring-doc.cadn.net.cn

import java.time.Duration;

import org.springframework.boot.cache.autoconfigure.CouchbaseCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration;

@Configuration(proxyBeanMethods = false)
public class MyCouchbaseCacheManagerConfiguration {

	@Bean
	public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() {
		return (builder) -> builder
				.withCacheConfiguration("cache1", CouchbaseCacheConfiguration
						.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
				.withCacheConfiguration("cache2", CouchbaseCacheConfiguration
						.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));

	}

}
import org.springframework.boot.cache.autoconfigure.CouchbaseCacheManagerBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyCouchbaseCacheManagerConfiguration {

	@Bean
	fun myCouchbaseCacheManagerBuilderCustomizer(): CouchbaseCacheManagerBuilderCustomizer {
		return CouchbaseCacheManagerBuilderCustomizer { builder ->
			builder
				.withCacheConfiguration(
					"cache1", CouchbaseCacheConfiguration
						.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10))
				)
				.withCacheConfiguration(
					"cache2", CouchbaseCacheConfiguration
						.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1))
				)
		}
	}

}

Redis

如果Redis可用且已配置,则RedisCacheManager是自动配置的。 启动时可以通过设置spring.cache.cache-names属性和缓存默认值可以通过以下方式配置spring.cache.redis.*性能。 例如,以下配置为缓存1缓存2存活时间为10分钟的缓存:spring-doc.cadn.net.cn

spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m
spring:
  cache:
    cache-names: "cache1,cache2"
    redis:
      time-to-live: "10m"
默认情况下,会添加一个键前缀,这样如果两个独立缓存使用相同的键,Redis 就不会有重叠键,也不会返回无效值。 如果你自己创建设置,强烈建议保持开启此设置RedisCacheManager.
你可以通过添加一个RedisCache配置 @Bean属于你自己的。 如果你需要自定义默认序列化策略,这会很有用。

如果你需要对配置有更多控制,可以考虑注册一个RedisCacheManagerBuilderCustomizer豆。 以下示例展示了一个自定义器,它配置了特定的生存时间缓存1缓存2:spring-doc.cadn.net.cn

import java.time.Duration;

import org.springframework.boot.cache.autoconfigure.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;

@Configuration(proxyBeanMethods = false)
public class MyRedisCacheManagerConfiguration {

	@Bean
	public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
		return (builder) -> builder
				.withCacheConfiguration("cache1", RedisCacheConfiguration
						.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
				.withCacheConfiguration("cache2", RedisCacheConfiguration
						.defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));

	}

}
import org.springframework.boot.cache.autoconfigure.RedisCacheManagerBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.cache.RedisCacheConfiguration
import java.time.Duration

@Configuration(proxyBeanMethods = false)
class MyRedisCacheManagerConfiguration {

	@Bean
	fun myRedisCacheManagerBuilderCustomizer(): RedisCacheManagerBuilderCustomizer {
		return RedisCacheManagerBuilderCustomizer { builder ->
			builder
				.withCacheConfiguration(
					"cache1", RedisCacheConfiguration
						.defaultCacheConfig().entryTtl(Duration.ofSeconds(10))
				)
				.withCacheConfiguration(
					"cache2", RedisCacheConfiguration
						.defaultCacheConfig().entryTtl(Duration.ofMinutes(1))
				)
		}
	}

}

咖啡因

Caffeine 是 Java 8 版本,取代了 Guava 缓存的支持。 如果含有咖啡因,则CaffeineCacheManager(由Spring Boot启动缓存starter)是自动配置的。 通过设置spring.cache.cache-names属性和可以通过以下其中一种(按所示顺序)进行自定义:spring-doc.cadn.net.cn

  1. 一个由以下方式定义的缓存规范spring.cache.caffeine.specspring-doc.cadn.net.cn

  2. 一个咖啡因规格豆子定义为spring-doc.cadn.net.cn

  3. 一个咖啡因豆子定义为spring-doc.cadn.net.cn

例如,以下配置为缓存1缓存2最大容量为500的缓存,寿命为10分钟spring-doc.cadn.net.cn

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

如果缓存加载器豆子被定义,自动关联到CaffeineCacheManager. 自从......缓存加载器将与缓存管理器管理的所有缓存关联,必须定义为CacheLoader<Object, Object>. 自动配置不考虑其他通用类型。spring-doc.cadn.net.cn

缓存2k

Cache2k 是一个内存缓存。 如果有 Cache2k Spring集成,则SpringCache2kCacheManager是自动配置的。spring-doc.cadn.net.cn

通过设置spring.cache.cache-names财产。 缓存默认值可以通过以下方式进行定制缓存2kBuilder定制器豆。 以下示例展示了一个自定义工具,将缓存容量配置为200条,有效期为5分钟:spring-doc.cadn.net.cn

import java.util.concurrent.TimeUnit;

import org.springframework.boot.cache.autoconfigure.Cache2kBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class MyCache2kDefaultsConfiguration {

	@Bean
	public Cache2kBuilderCustomizer myCache2kDefaultsCustomizer() {
		return (builder) -> builder.entryCapacity(200)
				.expireAfterWrite(5, TimeUnit.MINUTES);
	}

}
import org.springframework.boot.cache.autoconfigure.Cache2kBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.TimeUnit

@Configuration(proxyBeanMethods = false)
class MyCache2kDefaultsConfiguration {

	@Bean
	fun myCache2kDefaultsCustomizer(): Cache2kBuilderCustomizer {
		return Cache2kBuilderCustomizer { builder ->
			builder.entryCapacity(200)
				.expireAfterWrite(5, TimeUnit.MINUTES)
		}
	}
}

简单

如果找不到其他提供者,则采用简单的实现方式并发哈希图因为缓存存储已经配置好。 如果你的应用中没有缓存库,这是默认设置。 默认情况下,缓存会根据需要创建,但你可以通过设置缓存名称财产。 比如说,如果你只想要缓存1缓存2缓存,设置缓存名称性质如下:spring-doc.cadn.net.cn

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

如果你这样做了,而你的应用使用了未列出的缓存,那么运行时需要缓存时失败,启动时不会失败。 这类似于“真实”缓存提供者使用未声明缓存时的行为。spring-doc.cadn.net.cn

没有

什么时候@EnableCaching如果你的配置中存在,那么也需要合适的缓存配置。 如果你有自定义的“org.springframework.cache.CacheManager”,可以考虑单独定义它@Configuration类,这样你就可以在必要时覆盖它。 None 使用无作实现,在测试中非常有用,切片测试默认通过@AutoConfigureCacheSpring-boot-cache-test(Spring Boot缓存测试)模块已存在。spring-doc.cadn.net.cn

如果你需要在某个环境中使用无作缓存而不是自动配置的缓存管理器,可以把缓存类型设置为没有如下例所示:spring-doc.cadn.net.cn

spring.cache.type=none
spring:
  cache:
    type: "none"