天天看點

飛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