@CacheConfig??當前類中所有緩存方法詳解
在 Spring Cache 抽象中,@CacheConfig
是一個??類級別注解??,用于為??當前類中的所有緩存方法(如 @Cacheable
、@CachePut
、@CacheEvict
)提供默認配置??。其核心作用是??避免在每個方法上重復聲明相同的緩存參數??,提升代碼簡潔性和可維護性。
??一、核心屬性與應用場景??
@CacheConfig
支持以下核心屬性,用于定義類級別緩存的默認行為:
屬性 | 類型 | 是否必填 | 說明 |
---|---|---|---|
cacheNames | String[] | 否 | 緩存名稱的默認值(逗號分隔)。若方法注解未顯式指定 value /cacheNames ,則使用此配置。 |
keyGenerator | String | 否 | 鍵生成器的 Bean 名稱(默認使用 SimpleKeyGenerator )。 |
cacheManager | String | 否 | 緩存管理器的 Bean 名稱(默認使用全局配置的 cacheManager )。 |
keyPrefix | String | 否 | 緩存鍵的前綴(Spring 4.3+ 支持,優先級高于 keyGenerator 中的默認前綴邏輯)。 |
condition | String | 否 | 類級別緩存方法的全局條件(SpEL 表達式,僅當方法滿足條件時生效)。 |
unless | String | 否 | 類級別緩存方法的全局排除條件(SpEL 表達式,滿足條件時不緩存結果)。 |
??二、典型使用場景??
@CacheConfig
適用于??同一類中多個緩存方法需要共享相同配置??的場景,例如:
- 同一類中所有緩存操作使用相同的緩存名稱(如
userCache
)。 - 同一類中所有緩存方法使用自定義的鍵生成策略。
- 同一類中所有緩存方法需要統一的緩存管理器(如切換不同緩存實現)。
??三、具體用法示例??
??示例 1:統一緩存名稱??
假設一個 UserService
類中所有緩存方法都使用 userCache
作為緩存名稱,可通過 @CacheConfig(cacheNames = "userCache")
統一聲明,避免每個方法重復寫 value = "userCache"
。
@Service
@CacheConfig(cacheNames = "userCache") // 類級別統一緩存名稱
public class UserService {// 方法 1:使用類級別的 cacheNames(無需顯式聲明 value)@Cacheable(key = "#userId")public User getUserById(Long userId) {return userRepository.findById(userId).orElse(null);}// 方法 2:顯式聲明 cacheNames 會覆蓋類級別配置(可選)@Cacheable(value = "profileCache", key = "#userId")public UserProfile getUserProfile(Long userId) {return profileRepository.findById(userId).orElse(null);}
}
??示例 2:自定義鍵生成器??
若需要為類中所有緩存方法使用自定義的鍵生成邏輯(如拼接多個參數),可通過 keyGenerator
指定自定義的鍵生成器 Bean。
??步驟 1:定義自定義鍵生成器??
@Component("customKeyGenerator")
public class CustomKeyGenerator implements KeyGenerator {@Overridepublic Object generate(Object target, Method method, Object... params) {// 自定義鍵格式:類名::方法名::參數1::參數2...return String.format("%s::%s::%s", target.getClass().getSimpleName(), method.getName(), Arrays.toString(params));}
}
??步驟 2:在類上通過 @CacheConfig
引用??
@Service
@CacheConfig(cacheNames = "userCache",keyGenerator = "customKeyGenerator" // 使用自定義鍵生成器
)
public class UserService {@Cacheablepublic User getUserById(Long userId) {return userRepository.findById(userId).orElse(null);}@Cacheablepublic User updateUser(Long userId, User newUser) {return userRepository.save(newUser);}
}
此時,兩個方法的緩存鍵會自動生成為:
getUserById::[123]
(假設userId=123
)updateUser::[123, User{id=123,...}]
??示例 3:統一緩存管理器??
若應用需要為不同緩存類型(如本地緩存和分布式緩存)配置不同的緩存管理器,可通過 cacheManager
指定類級別的緩存管理器。
??步驟 1:配置多個緩存管理器??
@Configuration
public class CacheConfig {// 本地緩存管理器(Caffeine)@Beanpublic CacheManager caffeineCacheManager() {CaffeineCacheManager manager = new CaffeineCacheManager();manager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES));return manager;}// 分布式緩存管理器(Redis)@Beanpublic CacheManager redisCacheManager(RedisConnectionFactory factory) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));return RedisCacheManager.builder(factory).cacheDefaults(config).build();}
}
??步驟 2:在類上指定緩存管理器??
@Service
@CacheConfig(cacheManager = "redisCacheManager") // 使用 Redis 緩存管理器
public class UserService {@Cacheable(key = "#userId")public User getUserById(Long userId) {return userRepository.findById(userId).orElse(null);}
}
??示例 4:全局條件與排除條件??
通過 condition
和 unless
可以為類中所有緩存方法設置全局生效條件。
@Service
@CacheConfig(cacheNames = "userCache",condition = "#userId != null", // 僅當 userId 非空時緩存unless = "#result == null" // 結果為 null 時不緩存
)
public class UserService {@Cacheable(key = "#userId")public User getUserById(Long userId) {return userRepository.findById(userId).orElse(null);}
}
此時,若 userId
為 null
或查詢結果為 null
,則不會觸發緩存操作。
??四、注意事項??
??作用范圍限制??
@CacheConfig
僅對當前類中聲明的緩存方法(@Cacheable
、@CachePut
、@CacheEvict
)有效,對子類或兄弟類的方法無影響。??方法級注解優先級更高??
若方法級別的緩存注解(如@Cacheable(value = "profileCache")
)顯式聲明了某個屬性(如value
),則??方法級配置會覆蓋類級別的默認配置??。??屬性沖突處理??
cacheNames
:方法級未聲明時使用類級別;方法級聲明時覆蓋類級別。keyGenerator
/cacheManager
:方法級未聲明時使用類級別;方法級聲明時覆蓋類級別。condition
/unless
:類級別條件與方法級別條件為??邏輯與(AND)關系??(即兩者都滿足時才生效)。
??適用 Spring 版本??
@CacheConfig
自 Spring 3.2 引入,所有 Spring Boot 1.x 及以上版本均支持。
??五、總結??
@CacheConfig
是 Spring Cache 中用于??類級別緩存配置復用??的核心注解,通過它可以統一管理同一類中所有緩存方法的公共參數(如緩存名稱、鍵生成策略、緩存管理器等),顯著減少重復代碼,提升可維護性。結合方法級注解的靈活性,能夠高效應對不同業務場景的緩存需求。