diff --git a/src/org/redkale/util/Attribute.java b/src/org/redkale/util/Attribute.java index 869d6e198..0e35433c2 100644 --- a/src/org/redkale/util/Attribute.java +++ b/src/org/redkale/util/Attribute.java @@ -35,6 +35,8 @@ import static org.redkale.asm.Opcodes.*; *
  *  Attribute<Record, String> nameAction = new Attribute<Record, String>() {
  *
+ *      private java.lang.reflect.Type _gtype = String.class;
+ *
  *      @Override
  *      public String field() {
  *          return "name";
@@ -56,6 +58,11 @@ import static org.redkale.asm.Opcodes.*;
  *      }
  *
  *      @Override
+ *      public java.lang.reflect.Type genericType() {
+ *          return _gtype;
+ *      }
+ *
+ *      @Override
  *      public Class declaringClass() {
  *          return Record.class;
  *      }
@@ -84,6 +91,15 @@ public interface Attribute {
      */
     public Class type();
 
+    /**
+     * 返回字段的数据泛型
+     *
+     * @return 字段的数据泛型
+     */
+    default java.lang.reflect.Type genericType() {
+        return type();
+    }
+
     /**
      * 返回字段依附的类名
      *
@@ -348,7 +364,7 @@ public interface Attribute {
      * @return Attribute对象
      */
     public static  Attribute create(final Class clazz, String fieldalias, final Class fieldtype) {
-        return create(clazz, fieldalias, fieldtype, null, null, null);
+        return create(clazz, fieldalias, fieldtype, null, (Function) null, null);
     }
 
     /**
@@ -415,12 +431,16 @@ public interface Attribute {
         }
         final String fieldname = fieldalias;
         Class column = fieldtype;
+        java.lang.reflect.Type generictype = fieldtype;
         if (tfield != null) { // public tfield
             column = tfield.getType();
+            generictype = tfield.getGenericType();
         } else if (tgetter != null) {
             column = tgetter.getReturnType();
+            generictype = tgetter.getGenericReturnType();
         } else if (tsetter != null) {
             column = tsetter.getParameterTypes()[0];
+            generictype = tsetter.getGenericParameterTypes()[0];
         } else if (fieldtype == null) {
             throw new RuntimeException("[" + clazz + "]have no public field or setter or getter");
         }
@@ -441,7 +461,11 @@ public interface Attribute {
                 + fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array");
         }
         try {
-            return (Attribute) loader.loadClass(newDynName.replace('/', '.')).getDeclaredConstructor().newInstance();
+            Attribute rs = (Attribute) loader.loadClass(newDynName.replace('/', '.')).getDeclaredConstructor().newInstance();
+            java.lang.reflect.Field _gtype = rs.getClass().getDeclaredField("_gtype");
+            _gtype.setAccessible(true);
+            _gtype.set(rs, generictype);
+            return rs;
         } catch (Throwable ex) {
         }
         //---------------------------------------------------
@@ -449,7 +473,10 @@ public interface Attribute {
         MethodVisitor mv;
 
         cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + interDesc + columnDesc + ">;", "java/lang/Object", new String[]{supDynName});
-
+        { //_gtype
+            FieldVisitor fv = cw.visitField(ACC_PRIVATE, "_gtype", "Ljava/lang/reflect/Type;", null, null);
+            fv.visitEnd();
+        }
         { //构造方法
             mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null);
             mv.visitVarInsn(ALOAD, 0);
@@ -491,6 +518,14 @@ public interface Attribute {
             mv.visitMaxs(1, 1);
             mv.visitEnd();
         }
+        { //genericType
+            mv = cw.visitMethod(ACC_PUBLIC, "genericType", "()Ljava/lang/reflect/Type;", null, null);
+            mv.visitVarInsn(ALOAD, 0);
+            mv.visitFieldInsn(GETFIELD, newDynName, "_gtype", "Ljava/lang/reflect/Type;");
+            mv.visitInsn(ARETURN);
+            mv.visitMaxs(1, 1);
+            mv.visitEnd();
+        }
         { //declaringClass 方法
             mv = cw.visitMethod(ACC_PUBLIC, "declaringClass", "()Ljava/lang/Class;", null, null);
             mv.visitLdcInsn(Type.getType(clazz));
@@ -593,7 +628,11 @@ public interface Attribute {
             }
         }.loadClass(newDynName.replace('/', '.'), bytes);
         try {
-            return creatorClazz.getDeclaredConstructor().newInstance();
+            Attribute rs = creatorClazz.getDeclaredConstructor().newInstance();
+            java.lang.reflect.Field _gtype = rs.getClass().getDeclaredField("_gtype");
+            _gtype.setAccessible(true);
+            _gtype.set(rs, generictype);
+            return rs;
         } catch (Exception ex) {
             throw new RuntimeException(ex);
         }
@@ -613,6 +652,25 @@ public interface Attribute {
      * @return Attribute对象
      */
     public static  Attribute create(final Class clazz, final String fieldname, final Class fieldtype, final Function getter, final BiConsumer setter) {
+        return create(clazz, fieldname, fieldtype, fieldtype, getter, setter);
+    }
+
+    /**
+     * 根据Class、字段名、字段类型、getter和setter方法生成 Attribute 对象。 clazz、fieldname、fieldtype都不能为null
+     *
+     * @param               依附类的类型
+     * @param               字段类型
+     * @param clazz            指定依附的类
+     * @param fieldname        字段名
+     * @param fieldtype        字段类型
+     * @param fieldGenericType 字段泛型
+     * @param getter           getter方法
+     * @param setter           setter方法
+     *
+     * @return Attribute对象
+     */
+    public static  Attribute create(final Class clazz, final String fieldname, final Class fieldtype,
+        final java.lang.reflect.Type fieldGenericType, final Function getter, final BiConsumer setter) {
         Objects.requireNonNull(clazz);
         Objects.requireNonNull(fieldname);
         Objects.requireNonNull(fieldtype);
@@ -622,6 +680,11 @@ public interface Attribute {
                 return fieldtype;
             }
 
+            @Override
+            public java.lang.reflect.Type genericType() {
+                return fieldGenericType;
+            }
+
             @Override
             public Class declaringClass() {
                 return clazz;