From 50607df3ef0721e15fea18c5f11b3a76dfa27091 Mon Sep 17 00:00:00 2001 From: redkale Date: Thu, 21 Dec 2023 00:10:02 +0800 Subject: [PATCH] CacheAction --- .../java/org/redkale/asm/AsmMethodBoost.java | 114 +++++++++--------- .../org/redkale/cache/spi/CacheAction.java | 97 +++++++++++++-- .../cache/spi/CacheAsmMethodBoost.java | 3 +- .../cache/spi/CacheManagerService.java | 6 + .../redkale/lock/spi/LockAsmMethodBoost.java | 3 +- src/main/java/org/redkale/net/sncp/Sncp.java | 6 +- .../java/org/redkale/util/Environment.java | 3 +- 7 files changed, 160 insertions(+), 72 deletions(-) diff --git a/src/main/java/org/redkale/asm/AsmMethodBoost.java b/src/main/java/org/redkale/asm/AsmMethodBoost.java index b83055e6a..569217484 100644 --- a/src/main/java/org/redkale/asm/AsmMethodBoost.java +++ b/src/main/java/org/redkale/asm/AsmMethodBoost.java @@ -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 { return new AsmMethodBoosts(items); } + /** + * + * 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method) + * + * @param clazz Class + * + * @return Map + */ + public static Map getMethodBeans(Class clazz) { + Map rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz); + //返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多 + rs.values().forEach(AsmMethodBean::removeEmptyNames); + return rs; + } + + /** + * 获取需屏蔽的方法上的注解 + * + * @param method 方法 + * + * @return 需要屏蔽的注解 + */ + public abstract List> 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> 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 methodBeans = AsmMethodBoost.getMethodBeans(serviceType); return AsmMethodBean.get(methodBeans, method); @@ -173,60 +229,6 @@ public abstract class AsmMethodBoost { } } - /** - * - * 返回一个类所有方法的字节信息, key为: method.getName+':'+Type.getMethodDescriptor(method) - * - * @param clazz Class - * - * @return Map - */ - public static Map getMethodBeans(Class clazz) { - Map rs = MethodParamClassVisitor.getMethodParamNames(new HashMap<>(), clazz); - //返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多 - rs.values().forEach(AsmMethodBean::removeEmptyNames); - return rs; - } - - /** - * 获取需屏蔽的方法上的注解 - * - * @param method 方法 - * - * @return 需要屏蔽的注解 - */ - public abstract List> 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> 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 { } @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); } } } diff --git a/src/main/java/org/redkale/cache/spi/CacheAction.java b/src/main/java/org/redkale/cache/spi/CacheAction.java index 8da03a2d4..341c8e140 100644 --- a/src/main/java/org/redkale/cache/spi/CacheAction.java +++ b/src/main/java/org/redkale/cache/spi/CacheAction.java @@ -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 get(Supplier 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 asyncLock = new ConcurrentHashMap<>(); - String val = asyncLock.computeIfAbsent("aaa", t -> null); - System.out.println(asyncLock.size()); - System.out.println(val); + class CacheKey { + private String key; + } } diff --git a/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java b/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java index 8cf6af7d4..a3d895a6b 100644 --- a/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java +++ b/src/main/java/org/redkale/cache/spi/CacheAsmMethodBoost.java @@ -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 } diff --git a/src/main/java/org/redkale/cache/spi/CacheManagerService.java b/src/main/java/org/redkale/cache/spi/CacheManagerService.java index 42726bd35..978e3ba2a 100644 --- a/src/main/java/org/redkale/cache/spi/CacheManagerService.java +++ b/src/main/java/org/redkale/cache/spi/CacheManagerService.java @@ -400,6 +400,9 @@ public class CacheManagerService implements CacheManager, Service { @Override public T bothGet(final String hash, final String key, final Type type, boolean nullable, Duration localExpire, Duration remoteExpire, Supplier 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 CompletableFuture bothGetAsync(String hash, String key, Type type, boolean nullable, Duration localExpire, Duration remoteExpire, Supplier> supplier) { + if (!enabled) { + return supplier.get(); + } if (localExpire == null) { //只有远程缓存 Objects.requireNonNull(remoteExpire); return remoteGetAsync(hash, key, type, nullable, remoteExpire, supplier); diff --git a/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java b/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java index 09258d443..fc6610f0b 100644 --- a/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java +++ b/src/main/java/org/redkale/lock/spi/LockAsmMethodBoost.java @@ -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 } diff --git a/src/main/java/org/redkale/net/sncp/Sncp.java b/src/main/java/org/redkale/net/sncp/Sncp.java index 81b470091..333e36f1d 100644 --- a/src/main/java/org/redkale/net/sncp/Sncp.java +++ b/src/main/java/org/redkale/net/sncp/Sncp.java @@ -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) { diff --git a/src/main/java/org/redkale/util/Environment.java b/src/main/java/org/redkale/util/Environment.java index c1f1364d5..30b70924b 100644 --- a/src/main/java/org/redkale/util/Environment.java +++ b/src/main/java/org/redkale/util/Environment.java @@ -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;