Spring Boot对缓存的支持

https://docs.spring.io/spring-boot/docs/3.2.0/reference/htmlsingle/#io.caching

Spring Framework 支持透明地为应用程序添加缓存。其核心抽象将缓存应用于方法,从而根据缓存中的信息减少执行次数。缓存逻辑是透明地应用的,对调用者没有任何干扰。只要通过 @EnableCaching 注解启用缓存支持,Spring Boot 就会自动配置缓存基础结构。

简而言之,要为服务的操作添加缓存,请将其相关注解添加到该方法的上面,如下所示:

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

@Component
public class MyMathService {

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

}

此示例演示了如何在可能昂贵的操作上使用缓存。在调用 computePiDecimal 之前,抽象会在 piDecimals 缓存中查找匹配的条目。如果找到条目,缓存中的内容将立即返回给调用方,并且不会调用该方法。否则,将调用该方法,并在返回值之前更新缓存。

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

如果你没有添加任何特定的缓存库,Spring Boot 会自动配置一个使用内存中并发映射的简单提供程序。当需要缓存时(如前一个示例中的 piDecimals),此提供程序会为你创建它。简单提供程序不建议用于生产用途,但它非常适合入门并确保你了解这些功能。几乎所有的提供程序都需要明确配置应用程序中使用的每个缓存。一些提供程序提供了一种自定义由 spring.cache.cache-names 属性定义的默认缓存的方式。

提示:还可以透明地更新或驱逐缓存中的数据。

支持的缓存提供程序(Providers)

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

如果没有定义类型为 CacheManager 的 bean 或名为 cacheResolver 的 CacheResolver,Spring Boot 将尝试按以下顺序检测以下提供程序:

  • Generic
  • JCache (JSR-107) (EhCache 3, Hazelcast, Infinispan, 其它)
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Cache2k
  • Simple

此外,Spring Boot for Apache Geode 还提供了自动配置功能,以使用 Apache Geode 作为缓存提供程序。

提示:如果 CacheManager 是由 Spring Boot 自动配置的,则可以通过设置 spring.cache.type 属性来强制使用特定的缓存提供程序。如果您需要在某些环境(例如测试)中使用,请使用此属性。

提示:使用 spring-boot-starter-cache “Starter” 可以快速添加基本的缓存依赖项。该 Starter 会引入 spring-context-support。如果手动添加依赖项,则必须包含 spring-context-support 才能使用 JCache 或 Caffeine 支持。

如果 CacheManager 是由 Spring Boot 自动配置的,可以在其完全初始化之前通过公开实现 CacheManagerCustomizer 接口的 bean 来进一步调整其配置。以下示例设置了一个标志,表示不应将 null 值传递给基础映射:

import org.springframework.boot.autoconfigure.cache.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);
    }

}

注意:在前一个示例中,期望自动配置一个 ConcurrentMapCacheManager。如果不是这种情况(要么你提供了自己的配置,要么自动配置了不同的缓存提供程序),则不会调用自定义程序。你可以根据需要拥有任意数量的自定义程序,还可以使用 @OrderOrdered 对其进行排序。

Generic

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

JCache (JSR-107)

JCache 是通过在类路径上存在 javax.cache.spi.CachingProvider(即类路径上存在符合 JSR-107 规范的缓存库)来启动的,而 JCacheCacheManager 是由 spring-boot-starter-cache “Starter” 提供的。有多种符合规范的库可供选择,Spring Boot 为 Ehcache 3、Hazelcast 和 Infinispan 提供了依赖管理。还可以添加任何其它符合规范的库。

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

# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.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.Configuration bean,则使用它来定制它们。

将调用 org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer bean,并传入 CacheManager 的引用以进行完整定制。

提示:如果定义了标准的 javax.cache.CacheManager bean,则会自动将其包装在抽象所期望的 org.springframework.cache.CacheManager 实现中。不会对其应用进一步的定制。

Hazelcast

Spring Boot 对 Hazelcast 具有一般支持。如果已自动配置 HazelcastInstance,并且 com.hazelcast:hazelcast-spring 在类路径上,则会自动将其包装在 CacheManager 中。

注意
Hazelcast 可以作为符合 JCache 规范的缓存或符合 Spring CacheManager 规范的缓存使用。当将 spring.cache.type 设置为 hazelcast 时,Spring Boot 将使用基于 CacheManager 的实现。如果想将 Hazelcast 用作符合 JCache 规范的缓存,请将 spring.cache.type 设置为 jcache。如果有多个符合 JCache 规范的缓存提供程序,并且想强制使用 Hazelcast,则必须明确设置 JCache 提供程序。

Infinispan

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

spring.cache.infinispan.config=infinispan.xml

可以通过设置 spring.cache.cache-names 属性在启动时创建缓存。如果定义了自定义的 ConfigurationBuilder bean,则用于定制缓存。

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

Couchbase

如果 Spring Data Couchbase 可用并配置了 Couchbase,则会自动配置 CouchbaseCacheManager。可以通过设置 spring.cache.cache-names 属性在启动时创建其它缓存,并使用 spring.cache.couchbase.* 属性配置缓存的默认值。例如,以下配置将创建具有 10 分钟条目过期时间的 cache1cache2 缓存:

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

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

import java.time.Duration;

import org.springframework.boot.autoconfigure.cache.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)));

    }

}

Redis

如果 Redis 可用并已配置,将自动配置 RedisCacheManager。可以通过设置 spring.cache.cache-names 属性在启动时创建其它缓存,并使用 spring.cache.redis.* 属性配置缓存的默认值。例如,以下配置将创建具有 10 分钟生存时间的 cache1cache2 缓存:

spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m

注意:默认情况下,会添加一个键前缀,以便如果两个独立的缓存使用相同的键,Redis 不会有重叠的键,也无法返回无效的值。如果创建自己的 RedisCacheManager,强烈建议启用此设置。

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

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

import java.time.Duration;

import org.springframework.boot.autoconfigure.cache.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)));

    }

}

Caffeine

Caffeine 是 Guava 缓存的 Java 8 重写版本,它取代了对 Guava 的支持。如果存在 Caffeine,则会自动配置 CaffeineCacheManager(由 spring-boot-starter-cache “Starter” 提供)。可以通过设置 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 分钟:

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

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

Cache2k

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

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

import java.util.concurrent.TimeUnit;

import org.springframework.boot.autoconfigure.cache.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);
    }

}

Simple

如果找不到其它提供者,则会配置一个使用 ConcurrentHashMap 作为缓存存储的简单实现。如果在你的应用程序中没有缓存库,则这是默认设置。默认情况下,会按需创建缓存,但可以通过设置 cache-names 属性来限制可用缓存的列表。例如,如果只需要 cache1cache2 缓存,请按如下方式设置 cache-names 属性:

spring.cache.cache-names=cache1,cache2

如果你这样做,并且你的应用程序使用了未列出的缓存,那么当需要缓存时,它会在运行时失败,而不是在启动时失败。这与你使用未声明的缓存时“真正”的缓存提供者的行为类似。

None

当配置中存在 @EnableCaching 时,也需要一个合适的缓存配置。如果有自定义的 CacheManager,请考虑将其定义在一个单独的 @Configuration 类中,以便在必要时可以覆盖它。None 使用了一个在测试中很有用的无操作(no-op)实现,切片测试默认通过 @AutoConfigureCache 使用它。

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

spring.cache.type=none
  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值