您好,登錄后才能下訂單哦!
注釋介紹
@Cacheable
@Cacheable 的作用 主要針對(duì)方法配置,能夠根據(jù)方法的請(qǐng)求參數(shù)對(duì)其結(jié)果進(jìn)行緩存
@Cacheable 作用和配置方法
參數(shù) | 解釋 | example |
---|---|---|
value | 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè) | 例如: @Cacheable(value=”mycache”) @Cacheable(value={”cache1”,”cache2”} |
key | 緩存的 key,可以為空,如果指定要按照 SpEL 表達(dá)式編寫,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合 | @Cacheable(value=”testcache”,key=”#userName”) |
condition | 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進(jìn)行緩存 | @Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
實(shí)例
@Cacheable(value=”accountCache”),這個(gè)注釋的意思是,當(dāng)調(diào)用這個(gè)方法的時(shí)候,會(huì)從一個(gè)名叫 accountCache 的緩存中查詢,如果沒(méi)有,則執(zhí)行實(shí)際的方法(即查詢數(shù)據(jù)庫(kù)),并將執(zhí)行的結(jié)果存入緩存中,否則返回緩存中的對(duì)象。這里的緩存中的 key 就是參數(shù) userName,value 就是 Account 對(duì)象?!癮ccountCache”緩存是在 spring*.xml 中定義的名稱。
@Cacheable(value="accountCache")// 使用了一個(gè)緩存名叫 accountCache public Account getAccountByName(String userName) { // 方法內(nèi)部實(shí)現(xiàn)不考慮緩存邏輯,直接實(shí)現(xiàn)業(yè)務(wù) System.out.println("real query account."+userName); return getFromDB(userName); }
@CachePut
@CachePut 的作用 主要針對(duì)方法配置,能夠根據(jù)方法的請(qǐng)求參數(shù)對(duì)其結(jié)果進(jìn)行緩存,和 @Cacheable 不同的是,它每次都會(huì)觸發(fā)真實(shí)方法的調(diào)用
@CachePut 作用和配置方法
參數(shù) | 解釋 | example |
---|---|---|
value | 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè) | @CachePut(value=”my cache”) |
key | 緩存的 key,可以為空,如果指定要按照 SpEL 表達(dá)式編寫,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合 | @CachePut(value=”testcache”,key=”#userName”) |
condition | 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進(jìn)行緩存 | @CachePut(value=”testcache”,condition=”#userName.length()>2”) |
實(shí)例
@CachePut 注釋,這個(gè)注釋可以確保方法被執(zhí)行,同時(shí)方法的返回值也被記錄到緩存中,實(shí)現(xiàn)緩存與數(shù)據(jù)庫(kù)的同步更新。
@CachePut(value="accountCache",key="#account.getName()")// 更新accountCache 緩存 public Account updateAccount(Account account) { return updateDB(account); }
@CacheEvict
@CachEvict 的作用 主要針對(duì)方法配置,能夠根據(jù)一定的條件對(duì)緩存進(jìn)行清空
@CacheEvict 作用和配置方法
參數(shù) | 解釋 | example |
---|---|---|
value | 緩存的名稱,在 spring 配置文件中定義,必須指定至少一個(gè) | @CacheEvict(value=”my cache”) |
key | 緩存的 key,可以為空,如果指定要按照 SpEL 表達(dá)式編寫,如果不指定,則缺省按照方法的所有參數(shù)進(jìn)行組合 | @CacheEvict(value=”testcache”,key=”#userName”) |
condition | 緩存的條件,可以為空,使用 SpEL 編寫,返回 true 或者 false,只有為 true 才進(jìn)行緩存 | @CacheEvict(value=”testcache”,condition=”#userName.length()>2”) |
allEntries | 是否清空所有緩存內(nèi)容,缺省為 false,如果指定為 true,則方法調(diào)用后將立即清空所有緩存 | @CachEvict(value=”testcache”,allEntries=true) |
beforeInvocation | 是否在方法執(zhí)行前就清空,缺省為 false,如果指定為 true,則在方法還沒(méi)有執(zhí)行的時(shí)候就清空緩存,缺省情況下,如果方法執(zhí)行拋出異常,則不會(huì)清空緩存 | @CachEvict(value=”testcache”,beforeInvocation=true) |
實(shí)例
@CacheEvict(value="accountCache",key="#account.getName()")// 清空accountCache 緩存 public void updateAccount(Account account) { updateDB(account); } @CacheEvict(value="accountCache",allEntries=true)// 清空accountCache 緩存 public void reload() { reloadAll() } @Cacheable(value="accountCache",condition="#userName.length() <=4")// 緩存名叫 accountCache public Account getAccountByName(String userName) { // 方法內(nèi)部實(shí)現(xiàn)不考慮緩存邏輯,直接實(shí)現(xiàn)業(yè)務(wù) return getFromDB(userName); }
@CacheConfig
所有的@Cacheable()里面都有一個(gè)value=“xxx”的屬性,這顯然如果方法多了,寫起來(lái)也是挺累的,如果可以一次性聲明完 那就省事了, 所以,有了@CacheConfig這個(gè)配置,@CacheConfig is a class-level annotation that allows to share the cache names,如果你在你的方法寫別的名字,那么依然以方法的名字為準(zhǔn)。
@CacheConfig("books") public class BookRepositoryImpl implements BookRepository { @Cacheable public Book findBook(ISBN isbn) {...} }
條件緩存
下面提供一些常用的條件緩存
//@Cacheable將在執(zhí)行方法之前( #result還拿不到返回值)判斷condition,如果返回true,則查緩存; @Cacheable(value = "user", key = "#id", condition = "#id lt 10") public User conditionFindById(final Long id) //@CachePut將在執(zhí)行完方法后(#result就能拿到返回值了)判斷condition,如果返回true,則放入緩存; @CachePut(value = "user", key = "#id", condition = "#result.username ne 'zhang'") public User conditionSave(final User user) //@CachePut將在執(zhí)行完方法后(#result就能拿到返回值了)判斷unless,如果返回false,則放入緩存;(即跟condition相反) @CachePut(value = "user", key = "#user.id", unless = "#result.username eq 'zhang'") public User conditionSave2(final User user) //@CacheEvict, beforeInvocation=false表示在方法執(zhí)行之后調(diào)用(#result能拿到返回值了);且判斷condition,如果返回true,則移除緩存; @CacheEvict(value = "user", key = "#user.id", beforeInvocation = false, condition = "#result.username ne 'zhang'") public User conditionDelete(final User user)
@Caching
有時(shí)候我們可能組合多個(gè)Cache注解使用;比如用戶新增成功后,我們要添加id–>user;username—>user;email—>user的緩存;此時(shí)就需要@Caching組合多個(gè)注解標(biāo)簽了。
@Caching(put = { @CachePut(value = "user", key = "#user.id"), @CachePut(value = "user", key = "#user.username"), @CachePut(value = "user", key = "#user.email") }) public User save(User user) {
自定義緩存注解
比如之前的那個(gè)@Caching組合,會(huì)讓方法上的注解顯得整個(gè)代碼比較亂,此時(shí)可以使用自定義注解把這些注解組合到一個(gè)注解中,如:
@Caching(put = { @CachePut(value = "user", key = "#user.id"), @CachePut(value = "user", key = "#user.username"), @CachePut(value = "user", key = "#user.email") }) @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface UserSaveCache { }
這樣我們?cè)诜椒ㄉ鲜褂萌缦麓a即可,整個(gè)代碼顯得比較干凈。
@UserSaveCache public User save(User user)
擴(kuò)展
比如findByUsername時(shí),不應(yīng)該只放username–>user,應(yīng)該連同id—>user和email—>user一起放入;這樣下次如果按照id查找直接從緩存中就命中了
@Caching( cacheable = { @Cacheable(value = "user", key = "#username") }, put = { @CachePut(value = "user", key = "#result.id", condition = "#result != null"), @CachePut(value = "user", key = "#result.email", condition = "#result != null") } ) public User findByUsername(final String username) { System.out.println("cache miss, invoke find by username, username:" + username); for (User user : users) { if (user.getUsername().equals(username)) { return user; } } return null; }
其實(shí)對(duì)于:id—>user;username—->user;email—>user;更好的方式可能是:id—>user;username—>id;email—>id;保證user只存一份;如:
@CachePut(value="cacheName", key="#user.username", cacheValue="#user.username") public void save(User user) @Cacheable(value="cacheName", key="#user.username", cacheValue="#caches[0].get(#caches[0].get(#username).get())") public User findByUsername(String username)
SpEL上下文數(shù)據(jù)
Spring Cache提供了一些供我們使用的SpEL上下文數(shù)據(jù),下表直接摘自Spring官方文檔:
名稱 | 位置 | 描述 | 示例 |
---|---|---|---|
methodName | root對(duì)象 | 當(dāng)前被調(diào)用的方法名 | root.methodName |
method | root對(duì)象 | 當(dāng)前被調(diào)用的方法 | root.method.name |
target | root對(duì)象 | 當(dāng)前被調(diào)用的目標(biāo)對(duì)象 | root.target |
targetClass | root對(duì)象 | 當(dāng)前被調(diào)用的目標(biāo)對(duì)象類 | root.targetClass |
args | root對(duì)象 | 當(dāng)前被調(diào)用的方法的參數(shù)列表 | root.args[0] |
caches | root對(duì)象 | 當(dāng)前方法調(diào)用使用的緩存列表(如@Cacheable(value={“cache1”, “cache2”})),則有兩個(gè)cache | root.caches[0].name |
argument name | 執(zhí)行上下文 | 當(dāng)前被調(diào)用的方法的參數(shù),如findById(Long id),我們可以通過(guò)#id拿到參數(shù) | user.id |
result | 執(zhí)行上下文 | 方法執(zhí)行后的返回值(僅當(dāng)方法執(zhí)行之后的判斷有效,如‘unless','cache evict'的beforeInvocation=false) | result |
@CacheEvict(value = "user", key = "#user.id", condition = "#root.target.canCache() and #root.caches[0].get(#user.id).get().username ne #user.username", beforeInvocation = true) public void conditionUpdate(User user)
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。