我們知道一個(gè)程序的瓶頸在于數(shù)據(jù)庫(kù),我們也知道內(nèi)存的速度是大大快于硬盤的速度的。當(dāng)我們需要重復(fù)地獲取相同的數(shù)據(jù)的時(shí)候,我們一次又一次的請(qǐng)求數(shù)據(jù)庫(kù)或者遠(yuǎn)程服務(wù),導(dǎo)致大量的時(shí)間耗費(fèi)在數(shù)據(jù)庫(kù)查詢或者遠(yuǎn)程方法調(diào)用上,導(dǎo)致程序性能的惡化,這便是數(shù)據(jù)緩存要解決的問(wèn)題。
Spring緩存支持
Spring定義了org.springframework.cache.CacheManager和org.springframework.cache.Cache接口用來(lái)統(tǒng)一不同的緩存的技術(shù)。其中,CacheManager是Spring提供的各種緩存技術(shù)抽象接口,Cache接口包含緩存的各種操作(增加、刪除、獲得緩存,我們一般不會(huì)直接和此接口打交道)。
1.Spring支持的CacheManager
針對(duì)不同的緩存技術(shù),需要實(shí)現(xiàn)不同的CacheManager,Spring定義了如表所示的CacheManager實(shí)現(xiàn)。
| CacheManager | 描述 |
|---|---|
| SimpleCacheManager | 使用簡(jiǎn)單的Collection來(lái)存儲(chǔ)緩存,主要用來(lái)測(cè)試 |
| ConcurrentMapCacheManager | 使用ConcurrentMap來(lái)存儲(chǔ)緩存 |
| NoOpCacheManager | 僅測(cè)試用,不會(huì)實(shí)際存儲(chǔ)緩存 |
| EhCacheCacheManager | 使用EhCache作為緩存技術(shù) |
| GuavaCacheManager | 使用google guava的GuavaCache作為緩存技術(shù)(在1.5版本棄用了) |
| HazelcastCacheManager | 使用Hazelcast作為緩存技術(shù) |
| JCacheCacheManager | 支持JCache(JSR-107)標(biāo)準(zhǔn)的實(shí)現(xiàn)作為緩存技術(shù),如Apache Commons JCS |
| RedisCacheManager | 使用redis來(lái)作為緩存技術(shù) |
在我們使用任意一個(gè)實(shí)現(xiàn)的CacheManager的時(shí)候,需注冊(cè)實(shí)現(xiàn)的CacheManager的Bean,例如:
@Bean
public EhCacheCacheManager cacheManager(CacheManager ehCacheCacheManager) {
return new EhCacheCacheManager(ehCacheCacheManager);
}
當(dāng)然,每種緩存技術(shù)都有很多的額外配置,但配置cacheManager是必不可少的。
2.聲名式緩存注解
Spring提供了4個(gè)注解來(lái)聲明緩存規(guī)則(又是使用注解式的AOP的一個(gè)生動(dòng)例子)。這四個(gè)注解如表所示。
| 注解 | 解釋 |
|---|---|
| @Cacheable | 在方法執(zhí)行前,Spring先檢查緩存中是否有數(shù)據(jù),如果有數(shù)據(jù)就直接返回緩存中的數(shù)據(jù);如果沒(méi)有就調(diào)用方法,并將返回值放入緩存。 |
| @CachePut | 無(wú)論怎么樣,都會(huì)將方法的返回值放到緩存中。@CachePut的屬性和@Cacheable保持一致 |
| @CacheEvict | 將一條或多條數(shù)據(jù)從緩存中刪除 |
| @Caching | 可以通過(guò)該注解,組合多個(gè)注解策略在一個(gè)方法上 |
@Cacheable、@CachePut、@CacheEvit都有value屬性,指定的是要使用的緩存名稱;key屬性指定的是數(shù)據(jù)在緩存中的存儲(chǔ)的鍵。
3.開啟聲名式緩存支持
開啟聲名式緩存支持十分簡(jiǎn)單,只需在配置類上使用@EnableCaching注解即可,例如:
@Configuration
@EnableCaching
public class AppConfig {
}
Spring Boot的支持
在Spring中使用緩存技術(shù)的關(guān)鍵是配置CacheManager,而Spring Boot為我們自動(dòng)配置了多個(gè)CacheManager的實(shí)現(xiàn)。
Spring Boot的CacheManager的自動(dòng)配置放置在org.springframework.boot.autoconfigure.cache包中,如圖所示。
通過(guò)圖我們可以看出,Spring Boot為我們自動(dòng)配置了EhCacheCacheConfiguration(使用EhCache)、GenericCacheConfiguration(使用Collection)、GuavaCacheConfiguration(使用Guava)、HazelcastCacheConfiguration(使用Hazelcast)、InfinispanCacheConfiguration(使用Infinispan)、JCacheCacheConfiguration(使用JCache)、NoOpCacheConfiguration(不使用存儲(chǔ))、RedisCacheConfiguration(使用Redis)、SimpleCacheConfiguration(使用ConcurrentMap)。在不做任何額外配置的情況下,默認(rèn)使用的是SimpleCacheConfiguration,即使用ConcurrentMapCacheManager。
/*
* Copyright 2012-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.cache;
import java.util.List;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
/**
* Simplest cache configuration, usually used as a fallback.
*
* @author Stephane Nicoll
* @since 1.3.0
*/
@Configuration
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {
private final CacheProperties cacheProperties;
private final CacheManagerCustomizers customizerInvoker;
SimpleCacheConfiguration(CacheProperties cacheProperties,
CacheManagerCustomizers customizerInvoker) {
this.cacheProperties = cacheProperties;
this.customizerInvoker = customizerInvoker;
}
@Bean // 默認(rèn)使用ConcurrentMapCacheManager
public ConcurrentMapCacheManager cacheManager() {
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
cacheManager.setCacheNames(cacheNames);
}
return this.customizerInvoker.customize(cacheManager);
}
}
Spring Boot支持以“spring.cache”為前綴的屬性來(lái)配置緩存。
spring.cache.type= # 可選generic, ehcache, hazelcast, infinispan, jcache, redis, guava, simple, none
spring.cache.cache-names= # 程序啟動(dòng)時(shí)創(chuàng)建緩存名稱
spring.cache.ehcache.config= # ehcache配置文件地址
spring.cache.hazelcast.config= # hazelcast 配置文件地址
spring.cache.infinispan.config= # infinispan 配置文件地址
spring.cache.jcache.config= # jcache 配置文件地址
spring.cache.jcache.provider= #當(dāng)多個(gè) jcache實(shí)現(xiàn)在類路徑中的時(shí)候,指定jcache實(shí)現(xiàn)
spring.cache.guava.spec= # guava specs
在Spring Boot環(huán)境下,使用緩存技術(shù)只需在項(xiàng)目中導(dǎo)入相關(guān)緩存技術(shù)的依賴包,并在配置類使用@EnableCaching開啟緩存支持即可。
為監(jiān)控而生的多級(jí)緩存框架 layering-cache這是我開源的一個(gè)多級(jí)緩存框架的實(shí)現(xiàn),如果有興趣可以看一下