java用注解實現redis緩存


用注解實現redis緩存

@CacheConfig

主要用於配置該類中會用到的一些共用的緩存配置。示例:

@CacheConfig(cacheNames = "users")
public interface UserService {...}

配置了該數據訪問對象中返回的內容將存儲於名為users的緩存對象中,我們也可以不使用該注解,直接通過@Cacheable自己配置緩存集的名字來定義。

@Cacheable

可以標記在一個方法上,也可以標記在一個類上,表示該方法/類是支持緩存的;Spring會在其被調用后將其返回值緩存起來。下次利用同樣的參數來執行該方法時可以直接從緩存中獲取結果。
參數介紹
• value、cacheNames:兩個等同的參數(cacheNames為Spring 4新增,作為value的別名),用於指定緩存存儲的集合名。由於Spring 4中新增了@CacheConfig,因此在Spring 3中原本必須有的value屬性,也成為非必需項了
• key:緩存對象存儲在Map集合中的key值,非必需,缺省按照函數的所有參數組合作為key值,若自己配置需使用SpEL表達式,比如:@Cacheable(key = "#p0"):使用函數第一個參數作為緩存的key值,更多關於SpEL表達式的詳細內容可參考官方文檔
• condition:緩存對象的條件,非必需,也需使用SpEL表達式,只有滿足表達式條件的內容才會被緩存,比如:@Cacheable(key = "#p0", condition = "#p0.length() < 3"),表示只有當第一個參數的長度小於3的時候才會被緩存。
• unless:另外一個緩存條件參數,非必需,需使用SpEL表達式。它不同於condition參數的地方在於它的判斷時機,該條件是在函數被調用之后才做判斷的,所以它可以通過對result進行判斷。
• keyGenerator:用於指定key生成器,非必需。若需要指定一個自定義的key生成器,我們需要去實現org.springframework.cache.interceptor.KeyGenerator接口,並使用該參數來指定。需要注意的是:該參數與key是互斥的
• cacheManager:用於指定使用哪個緩存管理器,非必需。只有當有多個時才需要使用
• cacheResolver:用於指定使用那個緩存解析器,非必需。需通過org.springframework.cache.interceptor.CacheResolver接口來實現自己的緩存解析器,並用該參數指定。
示例如下:

@Cacheable(value = "user", key = "#id")
User selectUserById(final Integer id);

• 關於使用key屬性自定義key
用來指定Spring緩存方法的返回結果時對應的key,支持SpringEL表達式。沒有指定該屬性時,Spring將使用默認策略生成key。

使用方法參數時我們可以直接使用“#參數名”或者“#p+參數的index”(參數index按照順序從0開始)
例子:

 			@Cacheable(value="users", key="#id")
  			 public User find(Integer id) {
  			    return null;
  			 }
   			@Cacheable(value="users", key="#p0")
   			public User find(Integer id) {
  			    return null;
   			}
   			@Cacheable(value="users", key="#user.id")
   			public User find(User user) {
     				 return null;
   			}
   			@Cacheable(value="users", key="#p0.id")
 			  public User find(User user) {
  			    	return null;
 			  }

@CachePut

應用到寫數據的方法上,如新增/修改方法,調用方法時會自動把相應的數據放入緩存,示例如下:

@CachePut(value = "user", key = "#user.id")  
public User save(User user) {  
    users.add(user);  
    return user;  
}  

此時會以user.id做為緩存key,返回結果user做為值
@CachePut的參數與@Cacheable類似
@CacheEvict
應用到移除數據的方法上,如刪除方法,調用方法時會從緩存中移除相應的數據,示例如下:

@CacheEvict(value = "user", key = "#id")
void delete(final Integer id);

參數介紹
除了同@Cacheable一樣的參數之外,@CacheEvict還有下面兩個參數:
• allEntries:非必需,默認為false。當為true時,會移除所有數據
• beforeInvocation:非必需,默認為false,會在調用方法之后移除數據。當為true時,會在調用方法之前移除數據。

@解決數據一致性的兩種方式

1. 使用@CachePut

在“查詢”方法上添加@Cacheable(value=”testValue”, key= “#testKey”)注解,對方法的返回值進行緩存,在“新增/修改”方法上添加@CachePut(value=”testValue”, key= “#testKey”)注解,當方法調用成功后,會對緩存testValue上key值為testKey的緩存進行更新,更新內容為“新增/修改”的返回值,因此“查詢”方法與“新增/修改”方法的返回值類型應該一致。
E.g.
user實體包含屬性: id / username / userage / usersex

@CachePut(value = "user", key = "#user.id#user.name#user.pass")  //用id作為緩存的key
public User get(User user) {  
    User user = users.getById(user.id);  //id = 123; username = “zhangsan”; userage = 18; usersex = “1”;
    return user;  
}  
@CachePut(value = "user", key = "#user.id")  //方法調用成功后更新key = 123 的緩存
public User update(User user) {  
    userService.updateById(user);  //id = 123; username = “lisi”; 
    return user;  
}  

執行update方法后,當再次調用get(User user)查詢方法時,redis內user緩存上key = 123仍然存在且user實體會變為 :(id = 123; username = “zhangsan”; userage = ; usersex = “”;)
由於返回值造成了緩存與數據庫數據不一致的問題。

2. 使用@CacheEvict

在“查詢”方法上添加@Cacheable(value=”testValue”, key= “#testKey”)注解,對方法的返回值進行緩存,在“新增/修改”方法上添加@CacheEvict(value=”testValue”, key= “#testKey”)注解,當方法調用成功后,會刪除緩存testValue上key值為testKey的緩存。
由於緩存中testValue上的key = 123已經被刪除,再次調用“查詢”方法時,會直接查庫,因此不存在數據不一致的問題。

@Cacheable注解不生效的問題

1.內部方法的調用導致@Cacheable失效

@Cacheable是基於Spring AOP代理類,內部方法調用是不走代理的,@Cacheable是不起作用的

2.緩存的對象必須實現Serializable

問題

1.針對key的失效時間設置,未實現
2.分頁時的緩存較復雜,未實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM