以下是 @Cacheable
和 @CachePut
的詳細對比,涵蓋功能、執行流程、適用場景、參數配置及代碼示例:
1. 核心對比表格
特性 | @Cacheable | @CachePut |
---|---|---|
作用 | 緩存方法的返回結果,避免重復計算 | 執行方法并更新緩存,不覆蓋原有緩存 |
執行流程 | 緩存命中:直接返回緩存值,不執行方法 未命中:執行方法,緩存結果 | 始終執行方法,并將結果更新到緩存 |
適用場景 | 查詢操作(如get 方法) | 更新操作(如save 、update 方法) |
緩存行為 | 覆蓋原有緩存值(或按條件更新) | 追加或覆蓋緩存值(不刪除原有數據) |
是否執行方法 | 僅當緩存未命中時執行 | 始終執行方法 |
性能影響 | 最優(減少重復計算) | 稍高(需同時執行方法和更新緩存) |
2. 詳細對比說明
(1) @Cacheable
- 核心功能:根據方法參數生成緩存鍵(key),若緩存中存在對應鍵的值,則直接返回緩存值,否則執行方法并將結果存入緩存。
- 適用場景:查詢操作(如從數據庫或遠程服務獲取數據)。
- 參數配置:
value/cacheNames
:指定緩存名稱(必填)。key
:自定義緩存鍵(如#id
)。condition
:條件判斷是否緩存(如#result != null
)。unless
:條件判斷是否不緩存(如#result == null
)。
(2) @CachePut
- 核心功能:無論緩存是否存在,始終執行方法,并將方法結果更新到緩存中。
- 適用場景:更新操作(如保存或更新數據后同步更新緩存)。
- 參數配置:
value/cacheNames
:指定緩存名稱(必填)。key
:自定義緩存鍵(如#user.id
)。condition/unless
:控制是否更新緩存。
3. 代碼示例對比
場景:用戶信息的增刪改查
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;// @Cacheable:緩存查詢結果@Cacheable(value = "userCache", key = "#id")public User getUserById(Long id) {System.out.println("從數據庫查詢用戶ID:" + id);return userMapper.selectUserById(id);}// @CachePut:更新緩存(同時更新數據庫)@CachePut(value = "userCache", key = "#user.id")public User updateUser(User user) {System.out.println("更新用戶信息并緩存:ID=" + user.getId());userMapper.updateUser(user); // 更新數據庫return user;}
}
執行流程對比
方法 | @Cacheable流程 | @CachePut流程 |
---|---|---|
getUserById(1) | 1. 檢查userCache:1 是否存在2. 存在則返回緩存,不執行方法 3. 不存在則執行方法并緩存結果 | 不適用 |
updateUser(user) | 不適用 | 1. 始終執行方法(更新數據庫) 2. 將返回結果存入 userCache:user.id |
4. 關鍵參數對比
@Cacheable
參數 | 描述 | 示例值 |
---|---|---|
value | 緩存名稱(必填) | "userCache" |
key | 緩存鍵(默認#method.name + #root.args ) | "user_" + #id |
condition | 只有滿足條件時才緩存結果 | #result != null |
unless | 滿足條件時不緩存結果 | #result.age < 18 |
@CachePut
參數 | 描述 | 示例值 |
---|---|---|
value | 緩存名稱(必填) | "userCache" |
key | 緩存鍵(默認#method.name + #root.args ) | "user_" + #user.id |
condition | 只有滿足條件時才更新緩存 | #user.name != null |
5. 注意事項
-
組合使用場景:
-
更新操作:通常需要
@CachePut
和@CacheEvict
的組合,例如:@CacheEvict(value = "userCache", key = "#id") // 先刪除舊緩存 @CachePut(value = "userCache", key = "#user.id") // 再存入新數據 public User updateUser(User user, Long id) { ... }
-
新增操作:使用
@CachePut
將新數據存入緩存(如insertUser
方法)。
-
-
緩存一致性:
- 對于更新操作,需確保數據庫和緩存同時更新,避免數據不一致。
- 使用
@CacheEvict
清除舊緩存,再通過@CachePut
存入新數據。
-
性能權衡:
@CachePut
會強制執行方法,需評估是否影響性能。- 對于高頻寫操作,需結合緩存過期策略(如
time-to-live
)。
6. 總結表格
注解 | 作用 | 是否執行方法 | 適用場景 | 關鍵參數 |
---|---|---|---|---|
@Cacheable | 緩存方法結果,減少重復計算 | 僅當緩存未命中時執行 | 查詢操作(get ) | value , key , condition |
@CachePut | 更新緩存,確保數據一致性 | 始終執行方法 | 更新操作(update 、save ) | value , key , condition |
通過以上對比,可以清晰理解這兩個注解的差異和使用場景,從而在實際開發中合理選擇和組合使用。