CacheAction

This commit is contained in:
redkale
2023-12-21 00:10:02 +08:00
parent 00ead74204
commit 50607df3ef
7 changed files with 160 additions and 72 deletions

View File

@@ -28,6 +28,7 @@ import static org.redkale.asm.Opcodes.IRETURN;
import static org.redkale.asm.Opcodes.LLOAD;
import static org.redkale.asm.Opcodes.LRETURN;
import static org.redkale.asm.Opcodes.RETURN;
import org.redkale.inject.ResourceFactory;
import org.redkale.util.Utility;
/**
@@ -55,6 +56,61 @@ public abstract class AsmMethodBoost<T> {
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) {
Map<String, AsmMethodBean> methodBeans = AsmMethodBoost.getMethodBeans(serviceType);
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
public void doInstance(T service) {
public void doInstance(ResourceFactory resourceFactory, T service) {
for (AsmMethodBoost item : items) {
if (item != null) {
item.doInstance(service);
item.doInstance(resourceFactory, service);
}
}
}

View File

@@ -3,9 +3,17 @@
*/
package org.redkale.cache.spi;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
import java.lang.reflect.ParameterizedType;
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.util.Environment;
import org.redkale.util.TypeToken;
/**
*
@@ -20,16 +28,87 @@ import org.redkale.convert.json.JsonConvert;
*/
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() {
return JsonConvert.root().convertTo(this);
}
public static void main(String[] args) throws Throwable {
final ConcurrentHashMap<String, String> asyncLock = new ConcurrentHashMap<>();
String val = asyncLock.computeIfAbsent("aaa", t -> null);
System.out.println(asyncLock.size());
System.out.println(val);
class CacheKey {
private String key;
}
}

View File

@@ -19,6 +19,7 @@ import org.redkale.asm.MethodVisitor;
import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
import org.redkale.cache.Cached;
import org.redkale.inject.ResourceFactory;
import org.redkale.util.RedkaleException;
import org.redkale.util.TypeToken;
@@ -95,7 +96,7 @@ public class CacheAsmMethodBoost extends AsmMethodBoost {
}
@Override
public void doInstance(Object service) {
public void doInstance(ResourceFactory resourceFactory, Object service) {
//do nothing
}

View File

@@ -400,6 +400,9 @@ public class CacheManagerService implements CacheManager, Service {
@Override
public <T> T bothGet(final String hash, final String key, final Type type, boolean nullable,
Duration localExpire, Duration remoteExpire, Supplier<T> supplier) {
if (!enabled) {
return supplier.get();
}
if (localExpire == null) { //只有远程缓存
Objects.requireNonNull(remoteExpire);
return remoteGet(hash, key, type, nullable, remoteExpire, supplier);
@@ -432,6 +435,9 @@ public class CacheManagerService implements CacheManager, Service {
@Override
public <T> CompletableFuture<T> bothGetAsync(String hash, String key, Type type, boolean nullable,
Duration localExpire, Duration remoteExpire, Supplier<CompletableFuture<T>> supplier) {
if (!enabled) {
return supplier.get();
}
if (localExpire == null) { //只有远程缓存
Objects.requireNonNull(remoteExpire);
return remoteGetAsync(hash, key, type, nullable, remoteExpire, supplier);

View File

@@ -16,6 +16,7 @@ import org.redkale.asm.Label;
import org.redkale.asm.MethodVisitor;
import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
import org.redkale.inject.ResourceFactory;
import org.redkale.lock.Locked;
import org.redkale.util.RedkaleException;
@@ -81,7 +82,7 @@ public class LockAsmMethodBoost extends AsmMethodBoost {
}
@Override
public void doInstance(Object service) {
public void doInstance(ResourceFactory resourceFactory, Object service) {
//do nothing
}

View File

@@ -748,7 +748,7 @@ public abstract class Sncp {
c.set(service, agent == null ? null : agent.getName());
}
if (methodBoost != null) {
methodBoost.doInstance(service);
methodBoost.doInstance(resourceFactory, service);
}
return service;
} catch (RuntimeException rex) {
@@ -885,7 +885,7 @@ public abstract class Sncp {
c.set(service, info);
}
if (methodBoost != null) {
methodBoost.doInstance(service);
methodBoost.doInstance(resourceFactory, service);
}
return service;
} catch (Throwable ex) {
@@ -1092,7 +1092,7 @@ public abstract class Sncp {
RedkaleClassLoader.putReflectionField(newDynName.replace('/', '.'), c);
}
if (methodBoost != null) {
methodBoost.doInstance(service);
methodBoost.doInstance(resourceFactory, service);
}
return service;
} catch (Exception ex) {

View File

@@ -75,8 +75,7 @@ public class Environment implements java.io.Serializable {
}
throw new RedkaleException("Not found '" + key + "' value");
}
} else if ((pos1 >= 0 && pos2 < 0) || (pos1 < 0 && pos2 >= 0)) {
} else if ((pos1 >= 0 && pos2 < 0) || (pos1 < 0 && pos2 >= 0 && val.indexOf("#{") < 0)) {
throw new RedkaleException(val + " is illegal naming");
}
return val;