diff --git a/src/main/java/org/redkale/util/Reproduce.java b/src/main/java/org/redkale/util/Reproduce.java index 492465d24..875c51515 100644 --- a/src/main/java/org/redkale/util/Reproduce.java +++ b/src/main/java/org/redkale/util/Reproduce.java @@ -223,6 +223,8 @@ public interface Reproduce extends BiFunction { }; } // ------------------------------------------------------------------------------ + final boolean destIsMap = Map.class.isAssignableFrom(destClass); + final boolean srcIsMap = Map.class.isAssignableFrom(srcClass); final String supDynName = Reproduce.class.getName().replace('.', '/'); final String destClassName = destClass.getName().replace('.', '/'); final String srcClassName = srcClass.getName().replace('.', '/'); @@ -274,29 +276,57 @@ public interface Reproduce extends BiFunction { } final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname); - java.lang.reflect.Method setter = null; - try { - if (!field.getType().equals(destClass.getField(dfname).getType())) { - continue; + if (destIsMap) { + mv.visitVarInsn(ALOAD, 1); + mv.visitLdcInsn(dfname); + mv.visitVarInsn(ALOAD, 2); + Class st = field.getType(); + String td = Type.getDescriptor(st); + mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td); + if (st == boolean.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (st == byte.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (st == short.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (st == char.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); + } else if (st == int.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (st == float.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (st == long.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (st == double.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); } - } catch (Exception e) { - try { - char[] cs = dfname.toCharArray(); - cs[0] = Character.toUpperCase(cs[0]); - String dfname2 = new String(cs); - setter = destClass.getMethod("set" + dfname2, field.getType()); - } catch (Exception e2) { - continue; - } - } - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - String td = Type.getDescriptor(field.getType()); - mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td); - if (setter == null) { - mv.visitFieldInsn(PUTFIELD, destClassName, dfname, td); + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); + mv.visitInsn(POP); } else { - mv.visitMethodInsn(INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), false); + java.lang.reflect.Method setter = null; + try { + if (!field.getType().equals(destClass.getField(dfname).getType())) { + continue; + } + } catch (Exception e) { + try { + char[] cs = dfname.toCharArray(); + cs[0] = Character.toUpperCase(cs[0]); + String dfname2 = new String(cs); + setter = destClass.getMethod("set" + dfname2, field.getType()); + } catch (Exception e2) { + continue; + } + } + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + String td = Type.getDescriptor(field.getType()); + mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td); + if (setter == null) { + mv.visitFieldInsn(PUTFIELD, destClassName, dfname, td); + } else { + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), destClass.isInterface()); + } } } @@ -328,30 +358,57 @@ public interface Reproduce extends BiFunction { } final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname); - java.lang.reflect.Method setter = null; - java.lang.reflect.Field srcField = null; - char[] cs = dfname.toCharArray(); - cs[0] = Character.toUpperCase(cs[0]); - String dfname2 = new String(cs); - try { - setter = destClass.getMethod("set" + dfname2, getter.getReturnType()); - } catch (Exception e) { + if (destIsMap) { + Class st = getter.getReturnType(); + mv.visitVarInsn(ALOAD, 1); + mv.visitLdcInsn(dfname); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface()); + if (st == boolean.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (st == byte.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (st == short.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (st == char.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); + } else if (st == int.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (st == float.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (st == long.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (st == double.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + } + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); + mv.visitInsn(POP); + } else { + java.lang.reflect.Method setter = null; + java.lang.reflect.Field srcField = null; + char[] cs = dfname.toCharArray(); + cs[0] = Character.toUpperCase(cs[0]); + String dfname2 = new String(cs); try { - srcField = destClass.getField(dfname); - if (!getter.getReturnType().equals(srcField.getType())) { + setter = destClass.getMethod("set" + dfname2, getter.getReturnType()); + } catch (Exception e) { + try { + srcField = destClass.getField(dfname); + if (!getter.getReturnType().equals(srcField.getType())) { + continue; + } + } catch (Exception e2) { continue; } - } catch (Exception e2) { - continue; } - } - mv.visitVarInsn(ALOAD, 1); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), false); - if (srcField == null) { - mv.visitMethodInsn(INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), false); - } else { - mv.visitFieldInsn(PUTFIELD, destClassName, dfname, Type.getDescriptor(getter.getReturnType())); + mv.visitVarInsn(ALOAD, 1); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface()); + if (srcField == null) { + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), destClass.isInterface()); + } else { + mv.visitFieldInsn(PUTFIELD, destClassName, dfname, Type.getDescriptor(getter.getReturnType())); + } } } mv.visitVarInsn(ALOAD, 1); diff --git a/src/test/java/org/redkale/test/util/ReproduceTest.java b/src/test/java/org/redkale/test/util/ReproduceTest.java new file mode 100644 index 000000000..f2e73c97d --- /dev/null +++ b/src/test/java/org/redkale/test/util/ReproduceTest.java @@ -0,0 +1,41 @@ +/* + * + */ +package org.redkale.test.util; + +import java.util.*; +import org.junit.jupiter.api.Test; +import org.redkale.util.*; + +/** + * + * @author zhangjx + */ +public class ReproduceTest { + + public static void main(String[] args) throws Throwable { + ReproduceTest test = new ReproduceTest(); + test.run1(); + test.run2(); + } + + @Test + public void run1() throws Exception { + TestBean bean = new TestBean(); + bean.setId(222); + bean.time = 55555L; + bean.setName("haha"); + bean.setMap(Utility.ofMap("aa", "bbb")); + System.out.println(Reproduce.copy(Map.class, bean)); + } + + @Test + public void run2() throws Exception { + TestBean bean = new TestBean(); + bean.setId(222); + bean.time = 55555L; + bean.setName("haha"); + bean.setMap(Utility.ofMap("aa", "bbb")); + System.out.println(Reproduce.load(Map.class, TestInterface.class).apply(new HashMap(), bean)); + } +} diff --git a/src/test/java/org/redkale/test/util/TestBean.java b/src/test/java/org/redkale/test/util/TestBean.java index e9efd1eb6..b58898cc8 100644 --- a/src/test/java/org/redkale/test/util/TestBean.java +++ b/src/test/java/org/redkale/test/util/TestBean.java @@ -11,7 +11,7 @@ import java.util.Map; * * @author zhangjx */ -public class TestBean extends TestABean { +public class TestBean extends TestABean implements TestInterface { private String name; diff --git a/src/test/java/org/redkale/test/util/TestInterface.java b/src/test/java/org/redkale/test/util/TestInterface.java new file mode 100644 index 000000000..d0b461d6d --- /dev/null +++ b/src/test/java/org/redkale/test/util/TestInterface.java @@ -0,0 +1,21 @@ +/* + * + */ +package org.redkale.test.util; + +import java.util.Map; + +/** + * + * @author zhangjx + */ +public interface TestInterface { + + public int getId(); + + public Map getMap(); + + public void setId(int id); + + public void setMap(Map map); +}