天天看点

飞5的Spring Boot2(32)- 缓存

缓存

Spring框架提供为应用透明添加缓存的支持,核心思想是,将抽象应用到缓存方法,基于缓存中可用信息减少方法的执行。缓存逻辑的应用是透明的,不会干扰调用者。

飞5的Spring Boot2(32)- 缓存

简而言之,为服务的某个操作添加缓存跟为方法添加相应注解那样简单:

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

注意

你既可以使用标准的JSR-107 (JCache)注解,也可以使用Spring自己的缓存注解,这是透明的,我们强烈建议你不要混淆使用。

注意

透明的更新或驱除缓存数据是可以的。

支持的缓存提供商

缓存抽象不提供实际的存储,而是依赖于org.springframework.cache.Cache和org.springframework.cache.CacheManager接口的实现。只要通过@EnableCaching注解开启缓存支持,Spring Boot就会根据实现自动配置一个合适的CacheManager。

注 如果你使用的缓存设施beans不是基于接口的,确保启用proxyTargetClass,并设置其属性为@EnableCaching。

注 使用spring-boot-starter-cache‘Starter’可以快速添加所需缓存依赖,如果你是手动添加依赖,需要注意一些实现只有spring-context-support jar才提供。

如果你还没有定义一个CacheManager类型的bean,或一个名为cacheResolver的CacheResolver(查看CachingConfigurer),Spring Boot将尝试以下提供商(按这个顺序):

  • Generic
  • JCache (JSR-107)(EhCache 3, Hazelcast, Infinispan, etc)
  • EhCache 2.x
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Guava
  • Simple

注意

spring.cache.type属性可强制指定使用的缓存提供商,如果需要在一些环境(比如,测试)中禁用全部缓存也可以使用该属性。

如果CacheManager是Spring Boot自动配置的,你可以在它完全初始化前,通过实现CacheManagerCustomizer接口进一步配置,以下设置使用的缓存name:

1@Bean
2public CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
3 return new CacheManagerCustomizer<ConcurrentMapCacheManager>() {
4     @Override
5     public void customize(ConcurrentMapCacheManager cacheManager) {
6         cacheManager.setCacheNames(Arrays.asList("one", "two"));
7     }
8 };
9}      

注意

在以上示例中,需要配置一个ConcurrentMapCacheManager,如果没有配置,则自定义器(customizer)将不会被调用。自定义器你添加多少都可以,并可以使用@Order或Ordered对它们进行排序。

Generic

如果上下文定义至少一个org.springframework.cache.Cache bean,一个配置好的CacheManager包装着它们,那么将使用通用(Generic)缓存。

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也会尽力为缓存设置实现细节,如下例所示:

1#只有当有多个提供者时才需要
2spring.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.JCacheManagerCustomizerbean被引用CacheManager完全自定义引用。

注意

如果javax.cache.CacheManager定义了标准bean,它将自动包装在org.springframework.cache.CacheManager抽象所期望的实现中。没有进一步的定制应用于它。

EhCache 2.x

如果在classpath下的根目录可以找到一个名为ehcache.xml的文件,则缓存将使用EhCache 2.x。如果EhCache 2.x和这样的文件出现,那它们将用于启动缓存管理器,使用以下配置可提供替换的配置文件:

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

Hazelcast

Spring Boot为Hazelcast提供通常的支持,如果HazelcastInstance被自动配置,那它将自动包装进一个CacheManager。

如果出于某些原因,需要使用另一个不同的HazelcastInstance,你可以请求Spring Boot创建一个单独的实例,并只用于该CacheManager:

1spring.cache.hazelcast.config=classpath:config/my-cache-hazelcast.xml      

注意

如果以这种方式创建一个单独的HazelcastInstance,它将不会注册到应用上下文中。

Infinispan

Infinispan没有默认的配置文件位置,所以需要显式指定:

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

通过设置spring.cache.cache-names属性可以让缓存在启动时就被创建,如果定义了ConfigurationBuilder bean,它将用来定义该实例。

Couchbase

如果Couchbase可用,并配置好了,CouchbaseCacheManager将会自动配置,使用spring.cache.cache-names属性可以在启动时创建其他缓存。对Bucket的操作也是自动配置的,你可以使用customizer在另一个Bucket上创建其他缓存:假设你需要在“main” Bucket上存放两个缓存(foo和bar),在另一个Bucket上存放一个存活时间为2秒的biz缓存。首先,你通过配置创建两个缓存:

1spring.cache.cache-names=foo,bar      

然后定义其他@Configuration来配置另一个Bucket和biz缓存:

1@Configuration
 2public class CouchbaseCacheConfiguration {
 3    private final Cluster cluster;
 4    public CouchbaseCacheConfiguration(Cluster cluster) {
 5        this.cluster = cluster;
 6    }
 7    @Bean
 8    public Bucket anotherBucket() {
 9        return this.cluster.openBucket("another", "secret");
10    }
11    @Bean
12    public CacheManagerCustomizer<CouchbaseCacheManager> cacheManagerCustomizer() {
13        return c -> {
14            c.prepareCache("biz", CacheBuilder.newInstance(anotherBucket())
15                    .withExpirationInMillis(2000));
16        };
17    }
18}      

这个示例配置重用了通过自动配置的Cluster。

Redis

如果Redis可用,并配置好了,RedisCacheManager将被自动配置,使用spring.cache.cache-names可以在启动时创建其他缓存。

注意

默认会添加key前缀以防止两个单独的缓存使用相同的key,否则Redis将存在重复的key,有可能返回不可用的值。如果创建自己的RedisCacheManager,强烈建议你保留该配置处于启用状态。

Caffeine

Caffeine是Java8对Guava缓存的重写版本,在Spring Boot 2.0中将取代Guava。如果出现Caffeine,CaffeineCacheManager将会自动配置。使用spring.cache.cache-names属性可以在启动时创建缓存,并可以通过以下配置进行自定义(按顺序):

  • spring.cache.caffeine.spec定义的特殊缓存
  • com.github.benmanes.caffeine.cache.CaffeineSpec bean定义
  • com.github.benmanes.caffeine.cache.Caffeine bean定义

例如,以下配置创建一个foo和bar缓存,最大数量为500,存活时间为10分钟:

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

除此之外,如果定义了com.github.benmanes.caffeine.cache.CacheLoader,它会自动关联到CaffeineCacheManager。由于该CacheLoader将关联被该缓存管理器管理的所有缓存,所以它必须定义为CacheLoader,自动配置将忽略所有泛型类型。,>

Guava

如果存在Guava,GuavaCacheManager会自动配置。使用spring.cache.cache-names属性可以在启动时创建缓存,并通过以下方式之一自定义(按此顺序):

  • spring.cache.guava.spec定义的特殊缓存
  • com.google.common.cache.CacheBuilderSpec bean定义的
  • com.google.common.cache.CacheBuilder bean定义的

例如,以下配置创建了一个foo和bar缓存,该缓存最大数量为500,存活时间为10分钟:

1spring.cache.cache-names=foo,bar
2spring.cache.guava.spec=maximumSize=500,expireAfterAccess=600s      

此外,如果定义com.google.common.cache.CacheLoader bean,它会自动关联到GuavaCacheManager。由于该CacheLoader将关联该缓存管理器管理的所有缓存,它必须定义为CacheLoader,自动配置会忽略所有泛型类型。,>

Simple

None

1spring.cache.type=none