CombinedKey

This commit is contained in:
redkale
2023-12-21 07:54:30 +08:00
parent 50607df3ef
commit f9ec08adea
5 changed files with 161 additions and 17 deletions

View File

@@ -40,7 +40,7 @@ public @interface Cached {
*
* @return hash
*/
String map() default "";
String hash() default "";
/**
* 本地缓存过期时长, 0表示永不过期 -1表示不作本地缓存。<br>

View File

@@ -6,14 +6,18 @@ package org.redkale.cache.spi;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import org.redkale.annotation.Nullable;
import org.redkale.annotation.Resource;
import org.redkale.cache.CacheManager;
import org.redkale.cache.Cached;
import org.redkale.convert.json.JsonConvert;
import org.redkale.net.sncp.Sncp;
import org.redkale.util.Environment;
import org.redkale.util.TypeToken;
import org.redkale.util.CombinedKey;
/**
*
@@ -45,10 +49,18 @@ public class CacheAction {
//是否可以缓存null
private final boolean nullable;
//宿主对象的类
private final Class serviceClass;
//无法获取动态的Method只能存方法名
private final String methodName;
//方法参数类型
@Nullable
private final Class[] paramTypes;
//方法参数名
@Nullable
private final String[] paramNames;
//缓存的hash
@@ -57,24 +69,32 @@ public class CacheAction {
//缓存的key
private String key;
//缓存的key
private CombinedKey dynKey;
//本地缓存过期时长
private Duration localExpire;
//远程缓存过期时长
private Duration remoteExpire;
CacheAction(Cached cached, Type returnType, String[] paramNames, String methodName) {
CacheAction(Cached cached, Type returnType, Class serviceClass, Class[] paramTypes, String[] paramNames, String methodName) {
this.cached = cached;
this.nullable = cached.nullable();
this.serviceClass = Objects.requireNonNull(serviceClass);
this.paramTypes = paramTypes;
this.paramNames = paramNames;
this.methodName = methodName;
this.methodName = Objects.requireNonNull(methodName);
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
}
void init() {
this.hash = environment.getPropertyValue(cached.map());
this.hash = cached.hash().trim().isEmpty()
? Sncp.getResourceType(serviceClass).getSimpleName()
: environment.getPropertyValue(cached.hash());
this.key = environment.getPropertyValue(cached.key());
this.dynKey = CombinedKey.create(paramTypes, paramNames, key);
this.localExpire = createDuration(cached.localExpire());
this.remoteExpire = createDuration(cached.remoteExpire());
}
@@ -82,16 +102,12 @@ public class CacheAction {
public <T> T get(Supplier<T> supplier, Object... args) {
if (async) {
Supplier supplier0 = supplier;
return (T) manager.bothGetAsync(hash, keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier0);
return (T) manager.bothGetAsync(hash, dynKey.keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier0);
} else {
return manager.bothGet(hash, keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier);
return manager.bothGet(hash, dynKey.keyFor(args), resultType, nullable, localExpire, remoteExpire, supplier);
}
}
private String keyFor(Object... args) {
return "";
}
private Duration createDuration(String val) {
String str = environment.getPropertyValue(val);
if ("-1".equals(str) || "null".equalsIgnoreCase(str)) {
@@ -103,12 +119,20 @@ public class CacheAction {
}
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
class CacheKey {
private String key;
return "{"
+ "\"serviceClass\":" + serviceClass.getName()
+ ",\"methodName\":\"" + methodName + "\""
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(paramTypes)
+ ",\"paramNames\":" + JsonConvert.root().convertTo(paramNames)
+ ",\"hash\":\"" + cached.hash() + "\""
+ ",\"key\":" + JsonConvert.root().convertTo(key)
+ ",\"localExpire\":\"" + cached.localExpire() + "\""
+ ",\"remoteExpire\":\"" + cached.remoteExpire() + "\""
+ ",\"timeUnit\":\"" + cached.timeUnit() + "\""
+ ",\"nullable\":" + cached.nullable()
+ "}";
}
}

View File

@@ -29,7 +29,7 @@ public @interface DynForCache {
String key();
String map();
String hash();
String localExpire();

View File

@@ -0,0 +1,33 @@
/*
*
*/
package org.redkale.util;
/**
* 根据参数动态生成key
*
* <p>
* 详情见: https://redkale.org
*
*
* @author zhangjx
*
* @since 2.8.0
*/
public interface CombinedKey {
public String keyFor(Object... args);
/**
* 生成Key, paramTypes与paramNames长度必须一致
*
* @param paramTypes 参数类型
* @param paramNames 参数名
* @param key key表达式
*
* @return CombinedKey
*/
public static CombinedKey create(Class[] paramTypes, String[] paramNames, String key) {
return CombinedKeys.create(paramTypes, paramNames, key);
}
}

View File

@@ -0,0 +1,87 @@
/*
*
*/
package org.redkale.util;
import java.util.Objects;
/**
*
* @author zhangjx
*/
class CombinedKeys {
public static CombinedKey create(Class[] paramTypes, String[] paramNames, String key) {
Objects.requireNonNull(key, "key for " + CombinedKey.class.getSimpleName() + " is null");
if ((paramTypes != null && paramNames != null && paramTypes.length != paramNames.length)
|| (paramTypes == null && paramNames != null)
|| (paramTypes != null && paramNames == null)) {
throw new IllegalArgumentException("paramTypes.length and paramNames.length is inconsistent");
}
if (key.indexOf('{') < 0) {
return new StringDynamicKey(key);
} else {
if (paramNames != null) {
for (int i = 0; i < paramNames.length; i++) {
if (key.equalsIgnoreCase("#{" + paramNames[i] + "}")) {
return new ParamDynamicKey(i);
}
}
}
return new CombinedDynamicKey(paramTypes, paramNames, key);
}
}
static class CombinedDynamicKey implements CombinedKey {
private final CombinedKey[] keys;
public CombinedDynamicKey(Class[] paramTypes, String[] paramNames, String key) {
this.keys = new CombinedKey[0];
}
@Override
public String keyFor(Object... args) {
StringBuilder sb = new StringBuilder();
for (CombinedKey key : keys) {
sb.append(key.keyFor(args));
}
return sb.toString();
}
}
static class ParamDynamicKey implements CombinedKey {
private final int index;
public ParamDynamicKey(int index) {
this.index = index;
}
@Override
public String keyFor(Object... args) {
return String.valueOf(args[index]);
}
}
static class StringDynamicKey implements CombinedKey {
private final String key;
public StringDynamicKey(String key) {
this.key = key;
}
@Override
public String keyFor(Object... args) {
return key;
}
}
private CombinedKeys() {
//do nothing
}
}