SpringBoot @Cacheable自定義KeyGenerator方式
@Cacheable自定義KeyGenerator
1. 概述
SpringBoot 使用 @Cacheable 可以方便的管理緩存數(shù)據(jù),在不指定 key 屬性的情況下,默認(rèn)使用 SimpleKeyGenerator 生成 key。除此之外,我們也可以自定義實(shí)現(xiàn) KeyGenerator 接口,生成自己的 key 名稱策略。
2. MySimpleKey 類
MySimpleKey類的作用是存放參數(shù)數(shù)據(jù),必須實(shí)現(xiàn)equals、hashCode。如果需要自定義key格式,同樣需要實(shí)現(xiàn)toString接口,下面的例子是把參數(shù)用逗號(hào)分隔。
public class MySimpleKey implements Serializable {
public static final MySimpleKey EMPTY = new MySimpleKey(new Object[0]);
private final Object[] params;
private transient int hashCode;
public MySimpleKey(Object... elements) {
Assert.notNull(elements, "Elements must not be null");
this.params = (Object[])elements.clone();
this.hashCode = Arrays.deepHashCode(this.params);
}
public boolean equals(@Nullable Object other) {
return this == other || other instanceof MySimpleKey && Arrays.deepEquals(this.params, ((MySimpleKey)other).params);
}
public final int hashCode() {
return this.hashCode;
}
public String toString() {
return StringUtils.arrayToCommaDelimitedString(this.params);
}
}
3. MyKeyGenerator 類
MyKeyGenerator 實(shí)現(xiàn) KeyGenerator 的接口,里面只有一個(gè) generate 方法
public class MyKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object o, Method method, Object... objects) {
if (objects.length == 0) {
return MySimpleKey.EMPTY;
} else {
if (objects.length == 1) {
Object param = objects[0];
if (param != null && !param.getClass().isArray()) {
return param;
}
}
return new MySimpleKey(objects);
}
}
}
定義MyKeyGenerator Bean:
@Component
public class MyRedisConf {
@Bean
public MyKeyGenerator myKeyGenerator(){
return new MyKeyGenerator();
}
}
4. 配置keyGenerator
在 @Cacheable 配置 keyGenerator 屬性,值就是前面配置的Bean名稱
@Override
@Cacheable(value = {"REDIS:GETSTRING3"}, keyGenerator = "myKeyGenerator")
public String getString3(String tag, String name) {
return tag + " " + name;
}
測(cè)試結(jié)果如下,tag、name 參數(shù)確實(shí)以逗號(hào)分隔
127.0.0.1:6379[5]> KEYS *
1) "REDIS:GETSTRING3::hello,zhangsan"
Spring-Cache key設(shè)置
第一種方式:手動(dòng)設(shè)置
為了便于key的不重復(fù),我們可以手動(dòng)設(shè)置key有類名、方法名、參數(shù)等組合
| 屬性名稱 |
描述 |
示例 |
|
methodName |
當(dāng)前方法名 |
#root.methodName |
|
method |
當(dāng)前方法 |
#root.method.name |
|
target |
當(dāng)前被調(diào)用的對(duì)象 |
#root.target |
|
targetClass |
當(dāng)前被調(diào)用的對(duì)象的class |
#root.targetClass |
|
args |
當(dāng)前方法參數(shù)組成的數(shù)組 |
#root.args[0] |
|
caches |
當(dāng)前被調(diào)用的方法使用的Cache |
#root.caches[0].name |
key = "#root.targetClass.simpleName+':'+#root.methodName+':'+#param"
如下圖所示

第二種方式:自定義keyGenerator
1、自定義CacheKeyGenerator 實(shí)現(xiàn)KeyGenerator
public class CacheKeyGenerator implements KeyGenerator {
/**
* (非 Javadoc)
* <p>
* Title: generate
* </p>
*
* @param target
* @param method
* @param params
* @return
* @see org.springframework.cache.interceptor.KeyGenerator#generate(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder key = new StringBuilder();
key.append(target.getClass().getSimpleName()).append(":").append(method.getName()).append(":");
if (params.length == 0) {
return key.toString();
}
for (int i = 0; i < params.length; i++) {
Object param = params[i];
if (param == null || param instanceof LogableParam) {
del(key);
} else if (ClassUtils.isPrimitiveArray(param.getClass())) {
int length = Array.getLength(param);
for (int j = 0; j < length; j++) {
key.append(Array.get(param, j));
key.append(',');
}
} else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {
key.append(param);
} else {
key.append(param.toString());
}
key.append('-');
}
del(key);
return key.toString();
}
private StringBuilder del(StringBuilder stringBuilder) {
if (stringBuilder.toString().endsWith("-")) {
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
}
return stringBuilder;
}
}
2、配置xml
<cache:annotation-driven cache-manager="cacheManager" key-generator="cacheKeyGenerator"
proxy-target-class="true" />
<bean id="cacheKeyGenerator" class="com.tensoon.util.CacheKeyGenerator"></bean>
3、配置注解
如下圖所示

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java實(shí)現(xiàn)日歷(某年的日歷,某月的日歷)用戶完全自定義
本篇文章介紹了,java實(shí)現(xiàn)日歷(某年的日歷,某月的日歷)用戶完全自定義。需要的朋友參考下2013-05-05
使用okhttp替換Feign默認(rèn)Client的操作
這篇文章主要介紹了使用okhttp替換Feign默認(rèn)Client的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
Java was started but returned exit code=13問題解決案例詳解
這篇文章主要介紹了Java was started but returned exit code=13問題解決案例詳解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
MyBatis_Generator插件的安裝以及簡(jiǎn)單使用方法(圖解)
下面小編就為大家?guī)硪黄狹yBatis_Generator插件的安裝以及簡(jiǎn)單使用方法(圖解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
Spring中的@ControllerAdvice和@ExceptionHandler注解處理全局異常
這篇文章主要介紹了Spring中的@ControllerAdvice和@ExceptionHandler注解處理全局異常,@ControllerAdvice ,@ControllerAdvice是一個(gè)非常有用的注解,顧名思義,這是一個(gè)增強(qiáng)的 Controller,一般配合@ExceptionHandler使用來處理全局異常,需要的朋友可以參考下2024-01-01
Spring IOC推導(dǎo)與DI構(gòu)造器注入超詳細(xì)講解
這篇文章主要介紹了Spring IOC推導(dǎo)與DI構(gòu)造器注入,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2023-02-02

