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