diff --git a/src/main/java/org/redkale/util/Invoker.java b/src/main/java/org/redkale/util/Invoker.java index 621cc3965..b5ae8f790 100644 --- a/src/main/java/org/redkale/util/Invoker.java +++ b/src/main/java/org/redkale/util/Invoker.java @@ -6,6 +6,7 @@ package org.redkale.util; import java.lang.reflect.*; +import java.util.concurrent.ConcurrentHashMap; import org.redkale.asm.*; import static org.redkale.asm.Opcodes.*; import org.redkale.asm.Type; @@ -34,6 +35,16 @@ public interface Invoker { */ public RETURN_TYPE invoke(OBJECT_TYPE obj, Object... params); + public static Invoker load(final Class clazz, final String methodName, final Class... paramTypes) { + java.lang.reflect.Method method = null; + try { + method = clazz.getMethod(methodName, paramTypes); + } catch (Exception ex) { + throw new RedkaleException(ex); + } + return load(clazz, method); + } + public static Invoker create(final Class clazz, final String methodName, final Class... paramTypes) { java.lang.reflect.Method method = null; try { @@ -44,6 +55,12 @@ public interface Invoker { return create(clazz, method); } + public static Invoker load(final Class clazz, final Method method) { + return InvokerInner.caches + .computeIfAbsent(clazz, t -> new ConcurrentHashMap<>()) + .computeIfAbsent(method, v -> create(clazz, method)); + } + public static Invoker create(final Class clazz, final Method method) { RedkaleClassLoader.putReflectionDeclaredMethods(clazz.getName()); RedkaleClassLoader.putReflectionMethod(clazz.getName(), method); @@ -225,4 +242,9 @@ public interface Invoker { } } + static class InvokerInner { + + static final ConcurrentHashMap> caches = new ConcurrentHashMap(); + + } } diff --git a/src/main/java/org/redkale/util/Reproduce.java b/src/main/java/org/redkale/util/Reproduce.java index ac40a8a0d..492465d24 100644 --- a/src/main/java/org/redkale/util/Reproduce.java +++ b/src/main/java/org/redkale/util/Reproduce.java @@ -20,9 +20,27 @@ import static org.redkale.asm.Opcodes.*; */ public interface Reproduce extends BiFunction { + /** + * 将源对象字段复制到目标对象 + * + * @param dest 目标对象 + * @param src 源对象 + * + * @return 目标对象 + */ @Override public D apply(D dest, S src); + /** + * 将源对象字段复制到目标对象 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param dest 目标对象 + * @param src 源对象 + * + * @return 目标对象 + */ public static D copy(final D dest, final S src) { if (src == null || dest == null) { return null; @@ -32,6 +50,16 @@ public interface Reproduce extends BiFunction { return load(destClass, (Class) src.getClass()).apply(creator.create(), src); } + /** + * 将源对象字段复制到目标对象 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param src 源对象 + * + * @return 目标对象 + */ public static D copy(final Class destClass, final S src) { if (src == null) { return null; @@ -40,6 +68,16 @@ public interface Reproduce extends BiFunction { return load(destClass, (Class) src.getClass()).apply(creator.create(), src); } + /** + * 创建源类到目标类的复制器并缓存 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * + * @return 复制器 + */ public static Reproduce load(final Class destClass, final Class srcClass) { if (destClass == srcClass) { return ReproduceInner.reproduceOneCaches @@ -51,31 +89,139 @@ public interface Reproduce extends BiFunction { } } + /** + * 创建源类到目标类的复制器 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * + * @return 复制器 + */ public static Reproduce create(final Class destClass, final Class srcClass) { return create(destClass, srcClass, (BiPredicate) null, (Map) null); } + /** + * 创建源类到目标类的复制器 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * @param names 源字段名与目标字段名的映射关系 + * + * @return 复制器 + */ public static Reproduce create(final Class destClass, final Class srcClass, final Map names) { return create(destClass, srcClass, (BiPredicate) null, names); } + /** + * 创建源类到目标类的复制器 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * @param srcColumnPredicate 需复制的字段名判断期 + * + * @return 复制器 + */ @SuppressWarnings("unchecked") public static Reproduce create(final Class destClass, final Class srcClass, final Predicate srcColumnPredicate) { return create(destClass, srcClass, (sc, m) -> srcColumnPredicate.test(m), (Map) null); } + /** + * 创建源类到目标类的复制器 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * @param srcColumnPredicate 需复制的字段名判断期 + * @param names 源字段名与目标字段名的映射关系 + * + * @return 复制器 + */ @SuppressWarnings("unchecked") public static Reproduce create(final Class destClass, final Class srcClass, final Predicate srcColumnPredicate, final Map names) { return create(destClass, srcClass, (sc, m) -> srcColumnPredicate.test(m), names); } + /** + * 创建源类到目标类的复制器 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * @param srcColumnPredicate 需复制的字段名判断期 + * + * @return 复制器 + */ @SuppressWarnings("unchecked") public static Reproduce create(final Class destClass, final Class srcClass, final BiPredicate srcColumnPredicate) { return create(destClass, srcClass, srcColumnPredicate, (Map) null); } + /** + * 创建源类到目标类的复制器 + * + * @param 目标类泛型 + * @param 源类泛型 + * @param destClass 目标类名 + * @param srcClass 源类名 + * @param srcColumnPredicate 需复制的字段名判断期 + * @param names 源字段名与目标字段名的映射关系 + * + * @return 复制器 + */ @SuppressWarnings("unchecked") public static Reproduce create(final Class destClass, final Class srcClass, final BiPredicate srcColumnPredicate, final Map names) { + if (Map.class.isAssignableFrom(destClass) && Map.class.isAssignableFrom(srcClass)) { + final Map names0 = names; + if (srcColumnPredicate != null) { + if (names != null) { + return (D dest, S src) -> { + Map d = (Map) dest; + ((Map) src).forEach((k, v) -> { + if (srcColumnPredicate.test(null, k.toString())) { + d.put(names0.getOrDefault(k, k), v); + } + }); + return dest; + }; + } else { + return (D dest, S src) -> { + Map d = (Map) dest; + ((Map) src).forEach((k, v) -> { + if (srcColumnPredicate.test(null, k.toString())) { + d.put(k, v); + } + }); + return dest; + }; + } + } else if (names != null) { + return (D dest, S src) -> { + Map d = (Map) dest; + ((Map) src).forEach((k, v) -> { + d.put(names0.getOrDefault(k, k), v); + }); + return dest; + }; + } + return new Reproduce() { + @Override + public D apply(D dest, S src) { + ((Map) dest).putAll((Map) src); + return dest; + } + }; + } // ------------------------------------------------------------------------------ final String supDynName = Reproduce.class.getName().replace('.', '/'); final String destClassName = destClass.getName().replace('.', '/');