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.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user