CacheAction
This commit is contained in:
@@ -28,6 +28,7 @@ import static org.redkale.asm.Opcodes.IRETURN;
|
|||||||
import static org.redkale.asm.Opcodes.LLOAD;
|
import static org.redkale.asm.Opcodes.LLOAD;
|
||||||
import static org.redkale.asm.Opcodes.LRETURN;
|
import static org.redkale.asm.Opcodes.LRETURN;
|
||||||
import static org.redkale.asm.Opcodes.RETURN;
|
import static org.redkale.asm.Opcodes.RETURN;
|
||||||
|
import org.redkale.inject.ResourceFactory;
|
||||||
import org.redkale.util.Utility;
|
import org.redkale.util.Utility;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,6 +56,61 @@ public abstract class AsmMethodBoost<T> {
|
|||||||
return new AsmMethodBoosts(items);
|
return new AsmMethodBoosts(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method)
|
||||||
|
*
|
||||||
|
* @param clazz Class
|
||||||
|
*
|
||||||
|
* @return Map
|
||||||
|
*/
|
||||||
|
public static Map<String, AsmMethodBean> getMethodBeans(Class clazz) {
|
||||||
|
Map<String, AsmMethodBean> rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz);
|
||||||
|
//返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
||||||
|
rs.values().forEach(AsmMethodBean::removeEmptyNames);
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取需屏蔽的方法上的注解
|
||||||
|
*
|
||||||
|
* @param method 方法
|
||||||
|
*
|
||||||
|
* @return 需要屏蔽的注解
|
||||||
|
*/
|
||||||
|
public abstract List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对方法进行动态加强处理
|
||||||
|
*
|
||||||
|
* @param cw 动态字节码Writer
|
||||||
|
* @param newDynName 动态新类名
|
||||||
|
* @param fieldPrefix 动态字段的前缀
|
||||||
|
* @param filterAnns 需要过滤的注解
|
||||||
|
* @param method 操作的方法
|
||||||
|
* @param newMethodName 新的方法名, 可能为null
|
||||||
|
*
|
||||||
|
* @return 下一个新的方法名,不做任何处理应返回参数newMethodName
|
||||||
|
*/
|
||||||
|
public abstract String doMethod(ClassWriter cw, String newDynName, String fieldPrefix,
|
||||||
|
List<Class<? extends Annotation>> filterAnns, Method method, @Nullable String newMethodName);
|
||||||
|
|
||||||
|
/** 处理所有动态方法后调用
|
||||||
|
*
|
||||||
|
* @param cw 动态字节码Writer
|
||||||
|
* @param newDynName 动态新类名
|
||||||
|
* @param fieldPrefix 动态字段的前缀
|
||||||
|
*/
|
||||||
|
public abstract void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例对象进行操作,通常用于给动态的字段赋值
|
||||||
|
*
|
||||||
|
* @param resourceFactory ResourceFactory
|
||||||
|
* @param service 实例对象
|
||||||
|
*/
|
||||||
|
public abstract void doInstance(ResourceFactory resourceFactory, T service);
|
||||||
|
|
||||||
protected AsmMethodBean getMethodBean(Method method) {
|
protected AsmMethodBean getMethodBean(Method method) {
|
||||||
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
|
||||||
return AsmMethodBean.get(methodBeans, method);
|
return AsmMethodBean.get(methodBeans, method);
|
||||||
@@ -173,60 +229,6 @@ public abstract class AsmMethodBoost<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method)
|
|
||||||
*
|
|
||||||
* @param clazz Class
|
|
||||||
*
|
|
||||||
* @return Map
|
|
||||||
*/
|
|
||||||
public static Map<String, AsmMethodBean> getMethodBeans(Class clazz) {
|
|
||||||
Map<String, AsmMethodBean> rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz);
|
|
||||||
//返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
|
||||||
rs.values().forEach(AsmMethodBean::removeEmptyNames);
|
|
||||||
return rs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取需屏蔽的方法上的注解
|
|
||||||
*
|
|
||||||
* @param method 方法
|
|
||||||
*
|
|
||||||
* @return 需要屏蔽的注解
|
|
||||||
*/
|
|
||||||
public abstract List<Class<? extends Annotation>> filterMethodAnnotations(Method method);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 对方法进行动态加强处理
|
|
||||||
*
|
|
||||||
* @param cw 动态字节码Writer
|
|
||||||
* @param newDynName 动态新类名
|
|
||||||
* @param fieldPrefix 动态字段的前缀
|
|
||||||
* @param filterAnns 需要过滤的注解
|
|
||||||
* @param method 操作的方法
|
|
||||||
* @param newMethodName 新的方法名, 可能为null
|
|
||||||
*
|
|
||||||
* @return 下一个新的方法名,不做任何处理应返回参数newMethodName
|
|
||||||
*/
|
|
||||||
public abstract String doMethod(ClassWriter cw, String newDynName, String fieldPrefix,
|
|
||||||
List<Class<? extends Annotation>> filterAnns, Method method, @Nullable String newMethodName);
|
|
||||||
|
|
||||||
/** 处理所有动态方法后调用
|
|
||||||
*
|
|
||||||
* @param cw 动态字节码Writer
|
|
||||||
* @param newDynName 动态新类名
|
|
||||||
* @param fieldPrefix 动态字段的前缀
|
|
||||||
*/
|
|
||||||
public abstract void doAfterMethods(ClassWriter cw, String newDynName, String fieldPrefix);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 实例对象进行操作,通常用于给动态的字段赋值
|
|
||||||
*
|
|
||||||
* @param service 实例对象
|
|
||||||
*/
|
|
||||||
public abstract void doInstance(T service);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
|
* 生产动态字节码的方法扩展器, 可以进行方法加强动作
|
||||||
*
|
*
|
||||||
@@ -287,10 +289,10 @@ public abstract class AsmMethodBoost<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doInstance(T service) {
|
public void doInstance(ResourceFactory resourceFactory, T service) {
|
||||||
for (AsmMethodBoost item : items) {
|
for (AsmMethodBoost item : items) {
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.doInstance(service);
|
item.doInstance(resourceFactory, service);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,17 @@
|
|||||||
*/
|
*/
|
||||||
package org.redkale.cache.spi;
|
package org.redkale.cache.spi;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.lang.reflect.Type;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import org.redkale.annotation.Resource;
|
||||||
|
import org.redkale.cache.CacheManager;
|
||||||
|
import org.redkale.cache.Cached;
|
||||||
import org.redkale.convert.json.JsonConvert;
|
import org.redkale.convert.json.JsonConvert;
|
||||||
|
import org.redkale.util.Environment;
|
||||||
|
import org.redkale.util.TypeToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -20,16 +28,87 @@ import org.redkale.convert.json.JsonConvert;
|
|||||||
*/
|
*/
|
||||||
public class CacheAction {
|
public class CacheAction {
|
||||||
|
|
||||||
private Method method;
|
@Resource
|
||||||
|
private Environment environment;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private CacheManager manager;
|
||||||
|
|
||||||
|
private final Cached cached;
|
||||||
|
|
||||||
|
//Supplier对象的类型
|
||||||
|
private final Type resultType;
|
||||||
|
|
||||||
|
//对象是否异步
|
||||||
|
private final boolean async;
|
||||||
|
|
||||||
|
//是否可以缓存null
|
||||||
|
private final boolean nullable;
|
||||||
|
|
||||||
|
//无法获取动态的Method,只能存方法名
|
||||||
|
private final String methodName;
|
||||||
|
|
||||||
|
//方法参数名
|
||||||
|
private final String[] paramNames;
|
||||||
|
|
||||||
|
//缓存的hash
|
||||||
|
private String hash;
|
||||||
|
|
||||||
|
//缓存的key
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
//本地缓存过期时长
|
||||||
|
private Duration localExpire;
|
||||||
|
|
||||||
|
//远程缓存过期时长
|
||||||
|
private Duration remoteExpire;
|
||||||
|
|
||||||
|
CacheAction(Cached cached, Type returnType, String[] paramNames, String methodName) {
|
||||||
|
this.cached = cached;
|
||||||
|
this.nullable = cached.nullable();
|
||||||
|
this.paramNames = paramNames;
|
||||||
|
this.methodName = 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.key = environment.getPropertyValue(cached.key());
|
||||||
|
this.localExpire = createDuration(cached.localExpire());
|
||||||
|
this.remoteExpire = createDuration(cached.remoteExpire());
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
return manager.bothGet(hash, 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)) {
|
||||||
|
return null;
|
||||||
|
} else if ("0".equals(str)) {
|
||||||
|
return Duration.ZERO;
|
||||||
|
} else {
|
||||||
|
return Duration.ofMillis(cached.timeUnit().toMillis(Long.parseLong(str)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return JsonConvert.root().convertTo(this);
|
return JsonConvert.root().convertTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Throwable {
|
class CacheKey {
|
||||||
final ConcurrentHashMap<String, String> asyncLock = new ConcurrentHashMap<>();
|
private String key;
|
||||||
String val = asyncLock.computeIfAbsent("aaa", t -> null);
|
|
||||||
System.out.println(asyncLock.size());
|
|
||||||
System.out.println(val);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.redkale.asm.MethodVisitor;
|
|||||||
import static org.redkale.asm.Opcodes.*;
|
import static org.redkale.asm.Opcodes.*;
|
||||||
import org.redkale.asm.Type;
|
import org.redkale.asm.Type;
|
||||||
import org.redkale.cache.Cached;
|
import org.redkale.cache.Cached;
|
||||||
|
import org.redkale.inject.ResourceFactory;
|
||||||
import org.redkale.util.RedkaleException;
|
import org.redkale.util.RedkaleException;
|
||||||
import org.redkale.util.TypeToken;
|
import org.redkale.util.TypeToken;
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doInstance(Object service) {
|
public void doInstance(ResourceFactory resourceFactory, Object service) {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -400,6 +400,9 @@ public class CacheManagerService implements CacheManager, Service {
|
|||||||
@Override
|
@Override
|
||||||
public <T> T bothGet(final String hash, final String key, final Type type, boolean nullable,
|
public <T> T bothGet(final String hash, final String key, final Type type, boolean nullable,
|
||||||
Duration localExpire, Duration remoteExpire, Supplier<T> supplier) {
|
Duration localExpire, Duration remoteExpire, Supplier<T> supplier) {
|
||||||
|
if (!enabled) {
|
||||||
|
return supplier.get();
|
||||||
|
}
|
||||||
if (localExpire == null) { //只有远程缓存
|
if (localExpire == null) { //只有远程缓存
|
||||||
Objects.requireNonNull(remoteExpire);
|
Objects.requireNonNull(remoteExpire);
|
||||||
return remoteGet(hash, key, type, nullable, remoteExpire, supplier);
|
return remoteGet(hash, key, type, nullable, remoteExpire, supplier);
|
||||||
@@ -432,6 +435,9 @@ public class CacheManagerService implements CacheManager, Service {
|
|||||||
@Override
|
@Override
|
||||||
public <T> CompletableFuture<T> bothGetAsync(String hash, String key, Type type, boolean nullable,
|
public <T> CompletableFuture<T> bothGetAsync(String hash, String key, Type type, boolean nullable,
|
||||||
Duration localExpire, Duration remoteExpire, Supplier<CompletableFuture<T>> supplier) {
|
Duration localExpire, Duration remoteExpire, Supplier<CompletableFuture<T>> supplier) {
|
||||||
|
if (!enabled) {
|
||||||
|
return supplier.get();
|
||||||
|
}
|
||||||
if (localExpire == null) { //只有远程缓存
|
if (localExpire == null) { //只有远程缓存
|
||||||
Objects.requireNonNull(remoteExpire);
|
Objects.requireNonNull(remoteExpire);
|
||||||
return remoteGetAsync(hash, key, type, nullable, remoteExpire, supplier);
|
return remoteGetAsync(hash, key, type, nullable, remoteExpire, supplier);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.redkale.asm.Label;
|
|||||||
import org.redkale.asm.MethodVisitor;
|
import org.redkale.asm.MethodVisitor;
|
||||||
import static org.redkale.asm.Opcodes.*;
|
import static org.redkale.asm.Opcodes.*;
|
||||||
import org.redkale.asm.Type;
|
import org.redkale.asm.Type;
|
||||||
|
import org.redkale.inject.ResourceFactory;
|
||||||
import org.redkale.lock.Locked;
|
import org.redkale.lock.Locked;
|
||||||
import org.redkale.util.RedkaleException;
|
import org.redkale.util.RedkaleException;
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ public class LockAsmMethodBoost extends AsmMethodBoost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doInstance(Object service) {
|
public void doInstance(ResourceFactory resourceFactory, Object service) {
|
||||||
//do nothing
|
//do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -748,7 +748,7 @@ public abstract class Sncp {
|
|||||||
c.set(service, agent == null ? null : agent.getName());
|
c.set(service, agent == null ? null : agent.getName());
|
||||||
}
|
}
|
||||||
if (methodBoost != null) {
|
if (methodBoost != null) {
|
||||||
methodBoost.doInstance(service);
|
methodBoost.doInstance(resourceFactory, service);
|
||||||
}
|
}
|
||||||
return service;
|
return service;
|
||||||
} catch (RuntimeException rex) {
|
} catch (RuntimeException rex) {
|
||||||
@@ -885,7 +885,7 @@ public abstract class Sncp {
|
|||||||
c.set(service, info);
|
c.set(service, info);
|
||||||
}
|
}
|
||||||
if (methodBoost != null) {
|
if (methodBoost != null) {
|
||||||
methodBoost.doInstance(service);
|
methodBoost.doInstance(resourceFactory, service);
|
||||||
}
|
}
|
||||||
return service;
|
return service;
|
||||||
} catch (Throwable ex) {
|
} catch (Throwable ex) {
|
||||||
@@ -1092,7 +1092,7 @@ public abstract class Sncp {
|
|||||||
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
|
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
|
||||||
}
|
}
|
||||||
if (methodBoost != null) {
|
if (methodBoost != null) {
|
||||||
methodBoost.doInstance(service);
|
methodBoost.doInstance(resourceFactory, service);
|
||||||
}
|
}
|
||||||
return service;
|
return service;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ public class Environment implements java.io.Serializable {
|
|||||||
}
|
}
|
||||||
throw new RedkaleException("Not found '" + key + "' value");
|
throw new RedkaleException("Not found '" + key + "' value");
|
||||||
}
|
}
|
||||||
|
} else if ((pos1 >= 0 && pos2 < 0) || (pos1 < 0 && pos2 >= 0 && val.indexOf("#{") < 0)) {
|
||||||
} else if ((pos1 >= 0 && pos2 < 0) || (pos1 < 0 && pos2 >= 0)) {
|
|
||||||
throw new RedkaleException(val + " is illegal naming");
|
throw new RedkaleException(val + " is illegal naming");
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
|
|||||||
Reference in New Issue
Block a user