CombinedKey
This commit is contained in:
2
src/main/java/org/redkale/cache/Cached.java
vendored
2
src/main/java/org/redkale/cache/Cached.java
vendored
@@ -40,7 +40,7 @@ public @interface Cached {
|
|||||||
*
|
*
|
||||||
* @return hash
|
* @return hash
|
||||||
*/
|
*/
|
||||||
String map() default "";
|
String hash() default "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。<br>
|
* 本地缓存过期时长, 0表示永不过期, -1表示不作本地缓存。<br>
|
||||||
|
|||||||
@@ -6,14 +6,18 @@ package org.redkale.cache.spi;
|
|||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import org.redkale.annotation.Nullable;
|
||||||
import org.redkale.annotation.Resource;
|
import org.redkale.annotation.Resource;
|
||||||
import org.redkale.cache.CacheManager;
|
import org.redkale.cache.CacheManager;
|
||||||
import org.redkale.cache.Cached;
|
import org.redkale.cache.Cached;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
import org.redkale.net.sncp.Sncp;
|
||||||
import org.redkale.util.Environment;
|
import org.redkale.util.Environment;
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
|
import org.redkale.util.CombinedKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -45,10 +49,18 @@ public class CacheAction {
|
|||||||
//是否可以缓存null
|
//是否可以缓存null
|
||||||
private final boolean nullable;
|
private final boolean nullable;
|
||||||
|
|
||||||
|
//宿主对象的类
|
||||||
|
private final Class serviceClass;
|
||||||
|
|
||||||
//无法获取动态的Method,只能存方法名
|
//无法获取动态的Method,只能存方法名
|
||||||
private final String methodName;
|
private final String methodName;
|
||||||
|
|
||||||
|
//方法参数类型
|
||||||
|
@Nullable
|
||||||
|
private final Class[] paramTypes;
|
||||||
|
|
||||||
//方法参数名
|
//方法参数名
|
||||||
|
@Nullable
|
||||||
private final String[] paramNames;
|
private final String[] paramNames;
|
||||||
|
|
||||||
//缓存的hash
|
//缓存的hash
|
||||||
@@ -57,24 +69,32 @@ public class CacheAction {
|
|||||||
//缓存的key
|
//缓存的key
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
//缓存的key
|
||||||
|
private CombinedKey dynKey;
|
||||||
|
|
||||||
//本地缓存过期时长
|
//本地缓存过期时长
|
||||||
private Duration localExpire;
|
private Duration localExpire;
|
||||||
|
|
||||||
//远程缓存过期时长
|
//远程缓存过期时长
|
||||||
private Duration remoteExpire;
|
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.cached = cached;
|
||||||
this.nullable = cached.nullable();
|
this.nullable = cached.nullable();
|
||||||
|
this.serviceClass = Objects.requireNonNull(serviceClass);
|
||||||
|
this.paramTypes = paramTypes;
|
||||||
this.paramNames = paramNames;
|
this.paramNames = paramNames;
|
||||||
this.methodName = methodName;
|
this.methodName = Objects.requireNonNull(methodName);
|
||||||
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
|
this.async = CompletableFuture.class.isAssignableFrom(TypeToken.typeToClass(returnType));
|
||||||
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
|
this.resultType = this.async ? ((ParameterizedType) returnType).getActualTypeArguments()[0] : returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init() {
|
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.key = environment.getPropertyValue(cached.key());
|
||||||
|
this.dynKey = CombinedKey.create(paramTypes, paramNames, key);
|
||||||
this.localExpire = createDuration(cached.localExpire());
|
this.localExpire = createDuration(cached.localExpire());
|
||||||
this.remoteExpire = createDuration(cached.remoteExpire());
|
this.remoteExpire = createDuration(cached.remoteExpire());
|
||||||
}
|
}
|
||||||
@@ -82,16 +102,12 @@ public class CacheAction {
|
|||||||
public <T> T get(Supplier<T> supplier, Object... args) {
|
public <T> T get(Supplier<T> supplier, Object... args) {
|
||||||
if (async) {
|
if (async) {
|
||||||
Supplier supplier0 = supplier;
|
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 {
|
} 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) {
|
private Duration createDuration(String val) {
|
||||||
String str = environment.getPropertyValue(val);
|
String str = environment.getPropertyValue(val);
|
||||||
if ("-1".equals(str) || "null".equalsIgnoreCase(str)) {
|
if ("-1".equals(str) || "null".equalsIgnoreCase(str)) {
|
||||||
@@ -103,12 +119,20 @@ public class CacheAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonConvert.root().convertTo(this);
|
return "{"
|
||||||
}
|
+ "\"serviceClass\":" + serviceClass.getName()
|
||||||
|
+ ",\"methodName\":\"" + methodName + "\""
|
||||||
class CacheKey {
|
+ ",\"paramTypes\":" + JsonConvert.root().convertTo(paramTypes)
|
||||||
private String key;
|
+ ",\"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()
|
||||||
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public @interface DynForCache {
|
|||||||
|
|
||||||
String key();
|
String key();
|
||||||
|
|
||||||
String map();
|
String hash();
|
||||||
|
|
||||||
String localExpire();
|
String localExpire();
|
||||||
|
|
||||||
|
|||||||
33
src/main/java/org/redkale/util/CombinedKey.java
Normal file
33
src/main/java/org/redkale/util/CombinedKey.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/main/java/org/redkale/util/CombinedKeys.java
Normal file
87
src/main/java/org/redkale/util/CombinedKeys.java
Normal 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user