網(wǎng)站關(guān)鍵詞長尾詞推廣普通話繪畫
一、使用
在 Spring 中,使用緩存通常涉及以下步驟:
1、添加緩存依賴: 確保項目中添加了緩存相關(guān)的依賴。如果使用 Maven,可以在項目的 pom.xml 文件中添加 Spring Cache 的依賴。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2、配置緩存: 在 Spring 配置文件中進(jìn)行緩存的基本配置。如果是使用 Spring Boot,通常無需額外配置,因為 Spring Boot 提供了默認(rèn)的緩存配置。
第1步:在啟動類上加注解@EnableCaching
第2步:在具體方法上加注解【@CachePut、@CacheEvict、@Caching】或者在方法上添加 @Cacheable 注解: 在需要緩存的方法上使用 @Cacheable 注解,指定緩存的名稱、鍵等信息。
3、觸發(fā)緩存: 調(diào)用帶有 @Cacheable 注解的方法時,Spring 會檢查緩存中是否已經(jīng)有了相應(yīng)的結(jié)果。如果有,則直接返回緩存結(jié)果;如果沒有,則執(zhí)行方法體,計算結(jié)果并將結(jié)果緩存起來。
二、詳解
1、@Cacheable
@Cacheable 是 Spring Framework 中的一個注解,用于聲明某個方法的結(jié)果應(yīng)該被緩存,以便在后續(xù)調(diào)用中可以直接返回緩存的結(jié)果,而不需要再次執(zhí)行方法體。這個注解通常用于提高方法的執(zhí)行效率,尤其是對于那些計算成本較高的方法。
基本用法
import org.springframework.cache.annotation.Cacheable;public class MyService {@Cacheable(value = "myCache", key = "#input")public String getResult(String input) {// 如果緩存中存在以input為key的結(jié)果,則直接返回緩存結(jié)果// 否則,執(zhí)行方法體,并將結(jié)果緩存起來// ...}
}
在上述例子中:
@Cacheable 注解標(biāo)注在 getResult 方法上,表示該方法的結(jié)果將會被緩存。
value 屬性指定了緩存的名稱(可以有多個緩存,每個緩存有一個名稱)。
key 屬性指定了緩存的鍵,這里使用了 SpEL(Spring Expression Language)表達(dá)式,表示使用 input 參數(shù)的值作為緩存的鍵。有時候會按照下方書寫方式:
@Cacheable(value = "myCache", key = "#p0+','+#p1")
key = “#p0+‘,’+#p1” :指定緩存的鍵,使用了 Spring Expression Language(SpEL)的語法。#p0 表示方法的第一個參數(shù),#p1 表示方法的第二個參數(shù)。在這個例子中,鍵由第一個參數(shù)和第二個參數(shù)以逗號連接而成。這意味著如果兩次調(diào)用方法的時候,這兩個參數(shù)的值相同,那么它們會共享相同的緩存結(jié)果。如果想要每次調(diào)用方法都修改緩存值,可以用其他拼接符連接,比如橫杠、空格、冒號或者將方法名作為key值一部分。
key = "#p0 + '_' + #p1" // 使用下劃線key = "#p0 + ',' + #p1 + ',' + #p2" // 添加額外的參數(shù)或常量key = "methodName + ',' + #p0 + ',' + #p1" //使用方法名作為一部分
注意事項:
@Cacheable 注解需要在 Spring 環(huán)境中生效,因此通常需要在 Spring 的配置文件中啟用緩存功能。
方法的返回值類型應(yīng)該是可序列化的,以便能夠存儲在緩存中。
緩存的鍵是根據(jù) key 屬性生成的,所以確保它能夠唯一標(biāo)識方法的輸入?yún)?shù)。
@Cacheable 是 Spring Cache 抽象的一部分,而具體的緩存實現(xiàn)可以是基于不同的后端,比如基于內(nèi)存、Redis、Ehcache 等。
我們在使用的時候常常會和@SqlQuery注解一塊使用,如果一個方法同時使用了 @Cacheable 注解和 @SqlQuery 注解,那么其執(zhí)行流程通常如下:
-
首次調(diào)用: 當(dāng)方法被首次調(diào)用時,Spring 會先檢查緩存(由 @Cacheable
注解管理)。如果緩存中存在對應(yīng)的結(jié)果,則直接從緩存中取出并返回,而不會執(zhí)行實際的 SQL 查詢。 -
緩存未命中: 如果緩存中不存在對應(yīng)的結(jié)果,那么方法體會被執(zhí)行。在方法體中,可能會執(zhí)行 SQL 查詢(由 @SqlQuery
注解管理),并將查詢結(jié)果映射為方法的返回類型。 -
結(jié)果緩存: 如果啟用了 @Cacheable
注解,方法執(zhí)行完畢后,計算得到的結(jié)果會被緩存起來,以便下次相同的方法調(diào)用可以直接從緩存中獲取。
所以,如果緩存中已有相應(yīng)的結(jié)果,實際的 SQL 查詢可能不會執(zhí)行。這樣可以有效減輕對數(shù)據(jù)庫的訪問壓力,提高方法的執(zhí)行效率。在使用這兩個注解時,確保緩存的鍵和 SQL 查詢的參數(shù)不會引起混淆,以便正確地識別和管理緩存。
2、@CacheEvict
@CacheEvict 是 Spring 框架中用于清除緩存的注解。它用于標(biāo)記一個方法,在方法執(zhí)行時會清除指定緩存中的數(shù)據(jù)。以下是 @CacheEvict 注解的主要屬性和用法:
主要屬性:
value(或 cacheNames): 指定要清除的緩存的名稱,可以是一個字符串?dāng)?shù)組。例如:@CacheEvict(value = “myCache”) 或 @CacheEvict(cacheNames = {“cache1”, “cache2”})。
key: 指定用于生成緩存鍵的 SpEL 表達(dá)式。例如:@CacheEvict(value = "myCache", key = "#userI
condition: 指定清除緩存的條件,是一個 SpEL 表達(dá)式,如果表達(dá)式的值為 false,則不會清除緩存。例如:@CacheEvict(value = "myCache", condition = "#userId > 0")。
allEntries: 如果設(shè)置為 true,則會清除指定緩存中的所有條目。例如:@CacheEvict(value = "myCache", allEntries = true)
。
beforeInvocation: 如果設(shè)置為 true,則在方法調(diào)用之前清除緩存;如果設(shè)置為 false(默認(rèn)),則在方法調(diào)用之后清除緩存。例如:@CacheEvict(value = "myCache", beforeInvocation = true)
。
示例用法:
@Service
public class MyService {@CacheEvict(value = "myCache", key = "#userId")public void clearCacheByUserId(long userId) {// 此方法執(zhí)行時,會清除名為 "myCache" 中 key 為 userId 的緩存條目}@CacheEvict(value = "myCache", allEntries = true)public void clearEntireCache() {// 此方法執(zhí)行時,會清除名為 "myCache" 中的所有緩存條目}
}
在上述例子中,clearCacheByUserId 方法用于清除名為 “myCache” 中 key 為 userId 的緩存條目,而 clearEntireCache 方法用于清除 “myCache” 中的所有緩存條目。
請注意,@CacheEvict 注解通常用于在方法執(zhí)行時清除緩存。如果方法執(zhí)行拋出異常,緩存清除可能不會發(fā)生,除非設(shè)置了 beforeInvocation = true。因此,要確保清除緩存的操作是安全的,不會因為異常而導(dǎo)致緩存清除失敗。
3、@CachePut
@CachePut 是 Spring 框架中用于更新緩存的注解。它用于標(biāo)記一個方法,在方法執(zhí)行時會將結(jié)果放入緩存中。與 @Cacheable 不同,@CachePut 不會先檢查緩存中是否已有結(jié)果,而是直接將方法的返回值放入緩存中。
以下是 @CachePut 注解的主要屬性和用法:
主要屬性:
value(或 cacheNames): 指定要更新的緩存的名稱,可以是一個字符串?dāng)?shù)組。例如:@CachePut(value = "myCache") 或 @CachePut(cacheNames = {"cache1", "cache2"})
。
key: 指定用于生成緩存鍵的 SpEL 表達(dá)式。例如:@CachePut(value = "myCache", key = "#userId")
。
condition: 指定放入緩存的條件,是一個 SpEL 表達(dá)式,如果表達(dá)式的值為 false,則不會放入緩存。例如:@CachePut(value = "myCache", condition = "#userId > 0")
。
unless: 與 condition 相反,如果表達(dá)式的值為 true,則不會放入緩存。例如:@CachePut(value = "myCache", unless = "#result == null")
。
示例用法:
@Service
public class MyService {@CachePut(value = "myCache", key = "#userId")public String updateCacheByUserId(long userId) {// 此方法執(zhí)行時,會將返回值放入名為 "myCache" 中 key 為 userId 的緩存條目// 注意:不會先檢查緩存中是否已有結(jié)果,直接將方法的返回值放入緩存中// ...return "Updated Value";}
}
在上述例子中,updateCacheByUserId 方法用于將返回值放入名為 “myCache” 中 key 為 userId 的緩存條目。這個方法在執(zhí)行時,不會先檢查緩存中是否已有結(jié)果,而是直接將方法的返回值放入緩存中。
@CachePut 通常用于在更新操作之后,將最新的結(jié)果放入緩存,以保持緩存的一致性。需要注意的是,與 @Cacheable 不同,@CachePut 不會阻止方法的執(zhí)行,即使緩存操作失敗也不會影響方法的正常執(zhí)行。
4、@Caching
@Caching 是 Spring 框架中用于組合多個緩存注解的注解。它允許同時在一個方法上使用多個緩存相關(guān)的注解,包括 @Cacheable、@CachePut、@CacheEvict 等,從而提供更靈活的緩存配置。
示例用法:
@Service
public class MyService {@Caching(cacheable = {@Cacheable(value = "cache1", key = "#userId")},put = {@CachePut(value = "cache2", key = "#result.id")})public User getUserById(long userId) {// 先嘗試從 "cache1" 緩存中獲取結(jié)果// 如果獲取成功,則返回結(jié)果,不執(zhí)行方法體// 如果獲取失敗,則執(zhí)行方法體,并將結(jié)果放入 "cache1" 和 "cache2" 緩存中// ...return new User(userId, "John Doe");}
}
在上述例子中,@Caching 注解用于同時使用 @Cacheable 和 @CachePut 注解。具體來說:
@Cacheable 注解用于嘗試從名為 “cache1” 的緩存中獲取結(jié)果,如果獲取成功,則直接返回結(jié)果,不執(zhí)行方法體。
@CachePut 注解用于將方法的返回值放入名為 “cache2” 的緩存中,不論緩存中是否已有相同的鍵。
通過 @Caching 注解,可以更靈活地組合多個緩存注解,以滿足復(fù)雜的緩存需求。
三、cache失效時間配置
1、注解屬性中設(shè)置
在使用 @Cacheable 注解時,你可以通過設(shè)置 expire 或 expireAfterWrite 屬性來配置緩存的失效時間。這取決于使用的緩存管理器,因為不同的緩存管理器可能支持不同的配置。
例如,如果你使用的是 Spring Boot,并且底層的緩存管理器是基于 Caffeine 的,你可以使用 expireAfterWrite 屬性來設(shè)置失效時間。以下是一個示例:
@Cacheable(value = "myCache", key = "#input", expireAfterWrite = 5, timeUnit = TimeUnit.MINUTES)
public String getResult(String input) {// 如果緩存中存在以 input 為 key 的結(jié)果,則直接返回緩存結(jié)果// 否則,執(zhí)行方法體,并將結(jié)果緩存起來,緩存時間為 5 分鐘// ...
}
在上述示例中:
expireAfterWrite = 5 表示緩存項在寫入后經(jīng)過 5 分鐘過期。
timeUnit = TimeUnit.MINUTES 表示時間單位是分鐘。
具體的配置方式取決于使用的緩存管理器。如果你使用的是其他緩存管理器,例如 EhCache、Redis 等,具體的配置方式可能會有所不同。在配置文件或注解中查看相關(guān)屬性,以確保正確地設(shè)置緩存的失效時間。
2、redis管理器設(shè)置
當(dāng)使用 Redis 作為緩存管理器時,可以通過 Spring Boot 的配置文件或 Java 配置來設(shè)置 Redis 緩存的失效時間。以下是一個示例:
-
在 Spring Boot 的配置文件中設(shè)置 Redis 緩存失效時間: 在 application.properties 或
application.yml 文件中添加以下配置:# Redis 服務(wù)器地址 spring.redis.host=localhost # Redis 服務(wù)器端口 spring.redis.port=6379 # 緩存的默認(rèn)失效時間,單位秒 spring.cache.redis.time-to-live=600
-
上述配置中的 spring.cache.redis.time-to-live
表示緩存的默認(rèn)失效時間為600秒(10分鐘)。這個值會應(yīng)用于所有通過 @Cacheable、@CachePut 注解配置的緩存。在 Java 配置中設(shè)置 Redis 緩存失效時間: 如果你使用 Java 配置類,可以在配置類中通過
RedisCacheConfiguration 來設(shè)置緩存的失效時間。以下是一個示例:java @Configuration @EnableCaching public class CacheConfigextends CachingConfigurerSupport {@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600)); // 設(shè)置緩存失效時間為600秒(10分鐘)return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();} }
在上述配置中,
entryTtl(Duration.ofSeconds(600))
表示設(shè)置緩存的失效時間為600秒。這個值同樣會應(yīng)用于所有通過 @Cacheable、@CachePut 注解配置的緩存。
根據(jù)具體的需求,你可以根據(jù)緩存的特定性配置不同的失效時間。上述示例中僅作為演示,實際應(yīng)用中可以根據(jù)業(yè)務(wù)需求來設(shè)置合適的緩存失效時間。