All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redkale.util.Attribute Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkale.util;

import java.util.*;
import java.util.function.*;
import org.redkale.asm.*;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import static org.redkale.asm.Opcodes.*;

/**
 * 该类实现动态映射一个JavaBean类中成员对应的getter、setter方法; 代替低效的反射实现方式。
 * 
 *  public class Record {
 *
 *      private String name;
 *
 *      public String getName() {
 *          return name;
 *      }
 *
 *      public void setName(String name) {
 *          this.name = name;
 *      }
 *  }
 * 
* 获取name的 Attribute : *
 *  Attribute<Record, String> nameAction = Attribute.create(Record.class.getDeclaredField("name"));
 * 
* 等价于: *
 *  Attribute<Record, String> nameAction = new Attribute<Record, String>() {
 *
 *      @Override
 *      public String field() {
 *          return "name";
 *      }
 *
 *      @Override
 *      public String get(Record obj) {
 *          return obj.getName();
 *      }
 *
 *      @Override
 *      public void set(Record obj, String value) {
 *          obj.setName(value);
 *      }
 *
 *      @Override
 *      public Class type() {
 *          return String.class;
 *      }
 *
 *      @Override
 *      public Class declaringClass() {
 *          return Record.class;
 *      }
 *  };
 * 
*

* 映射Field时,field必须满足以下条件之一:
* 1、field属性是public且非final
* 2、至少存在对应的getter、setter方法中的一个
* 当不存在getter方法时,get操作固定返回null
* 当不存在setter方法时,set操作为空方法
*

* 详情见: https://redkale.org * * @author zhangjx * @param 字段依附的类 * @param 字段的数据类型 */ @SuppressWarnings("unchecked") public interface Attribute { /** * 返回字段的数据类型 * * @return 字段的数据类型 */ public Class type(); /** * 返回字段依附的类名 * * @return 依附的类名 */ public Class declaringClass(); /** * 返回字段名 * * @return 字段名 */ public String field(); /** * 获取指定对象的该字段的值 * * @param obj 指定对象 * * @return 字段的值 */ public F get(T obj); /** * 给指定对象的该字段赋值 * * @param obj 指定对象 * @param value 字段新值 */ public void set(T obj, F value); /** * 根据一个Field生成 Attribute 对象。 * * @param 依附类的类型 * @param 字段类型 * @param field 字段,如果该字段不存在则抛异常 * * @return Attribute对象 */ @SuppressWarnings("unchecked") public static Attribute create(final java.lang.reflect.Field field) { return create((Class) field.getDeclaringClass(), field.getName(), field, null, null); } /** * 根据一个Field和field的别名生成 Attribute 对象。 * * @param 依附类的类型 * @param 字段类型 * @param fieldalias 别名 * @param field 字段,如果该字段不存在则抛异常 * * @return Attribute对象 */ @SuppressWarnings("unchecked") public static Attribute create(String fieldalias, final java.lang.reflect.Field field) { return create((Class) field.getDeclaringClass(), fieldalias, field, null, null); } /** * 根据一个Class和field真实名称生成 Attribute 对象。 * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldname 字段名,如果该字段不存在则抛异常 * * @return Attribute对象 */ public static Attribute create(Class clazz, final String fieldname) { try { return create(clazz, fieldname, clazz.getDeclaredField(fieldname), null, null); } catch (NoSuchFieldException | SecurityException ex) { throw new RuntimeException(ex); } } /** * 根据一个Class和Field生成 Attribute 对象。 * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param field 字段,如果该字段不存在则抛异常 * * @return Attribute对象 */ public static Attribute create(Class clazz, final java.lang.reflect.Field field) { return create(clazz, field.getName(), field); } /** * 根据一个Class、field别名和Field生成 Attribute 对象。 * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldalias 字段别名 * @param field 字段,如果该字段不存在则抛异常 * * @return Attribute对象 */ public static Attribute create(Class clazz, final String fieldalias, final java.lang.reflect.Field field) { return create(clazz, fieldalias, field, null, null); } /** * 根据一个getter和setter方法生成 Attribute 对象。 tgetter、setter不能同时为null * * @param 依附类的类型 * @param 字段类型 * @param getter getter方法 * @param setter setter方法 * * @return Attribute对象 */ @SuppressWarnings("unchecked") public static Attribute create(final java.lang.reflect.Method getter, final java.lang.reflect.Method setter) { return create((Class) (getter == null ? setter.getDeclaringClass() : getter.getDeclaringClass()), null, null, getter, setter); } /** * 根据Class、getter和setter方法生成 Attribute 对象。 tgetter、setter不能同时为null * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param getter getter方法 * @param setter setter方法 * * @return Attribute对象 */ public static Attribute create(Class clazz, final java.lang.reflect.Method getter, final java.lang.reflect.Method setter) { return create(clazz, null, null, getter, setter); } /** * 根据Class生成getter、setter方法都存在的字段对应的 Attribute 对象数组。 * * @param 依附类的类型 * @param clazz 指定依附的类 * * @return Attribute对象数组 */ public static Attribute[] create(Class clazz) { List> list = new ArrayList<>(); for (java.lang.reflect.Field field : clazz.getFields()) { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) continue; if (java.lang.reflect.Modifier.isFinal(field.getModifiers())) continue; list.add(create(clazz, field)); } for (java.lang.reflect.Method setter : clazz.getDeclaredMethods()) { if (java.lang.reflect.Modifier.isStatic(setter.getModifiers())) continue; if (!setter.getName().startsWith("set")) continue; if (setter.getReturnType() != void.class) continue; if (setter.getParameterCount() != 1) continue; Class t = setter.getParameterTypes()[0]; String prefix = t == boolean.class || t == Boolean.class ? "is" : "get"; java.lang.reflect.Method getter = null; try { getter = clazz.getMethod(setter.getName().replaceFirst("set", prefix)); } catch (Exception e) { continue; } list.add(create(clazz, getter, setter)); } return list.toArray(new Attribute[list.size()]); } /** * 根据Class生成getter方法对应的 Attribute 对象数组。 * * @param 依附类的类型 * @param clazz 指定依附的类 * * @return Attribute对象数组 */ public static Attribute[] createGetters(Class clazz) { List> list = new ArrayList<>(); for (java.lang.reflect.Field field : clazz.getFields()) { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) continue; if (java.lang.reflect.Modifier.isFinal(field.getModifiers())) continue; list.add(create(clazz, field)); } for (java.lang.reflect.Method method : clazz.getDeclaredMethods()) { if (java.lang.reflect.Modifier.isStatic(method.getModifiers())) continue; if (!method.getName().startsWith("get") && !method.getName().startsWith("is")) continue; if (method.getReturnType() == void.class) continue; if (method.getParameterCount() != 0) continue; list.add(create(clazz, method, null)); } return list.toArray(new Attribute[list.size()]); } /** * 根据Class生成setter方法对应的 Attribute 对象数组。 * * @param 依附类的类型 * @param clazz 指定依附的类 * * @return Attribute对象数组 */ public static Attribute[] createSetters(Class clazz) { List> list = new ArrayList<>(); for (java.lang.reflect.Field field : clazz.getFields()) { if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) continue; if (java.lang.reflect.Modifier.isFinal(field.getModifiers())) continue; list.add(create(clazz, field)); } for (java.lang.reflect.Method method : clazz.getDeclaredMethods()) { if (java.lang.reflect.Modifier.isStatic(method.getModifiers())) continue; if (!method.getName().startsWith("set")) continue; if (method.getParameterCount() != 1) continue; list.add(create(clazz, null, method)); } return list.toArray(new Attribute[list.size()]); } /** * 根据Class、字段别名、getter和setter方法生成 Attribute 对象。 tgetter、setter不能同时为null * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldalias 字段别名 * @param getter getter方法 * @param setter setter方法 * * @return Attribute对象 */ public static Attribute create(Class clazz, final String fieldalias, final java.lang.reflect.Method getter, final java.lang.reflect.Method setter) { return create(clazz, fieldalias, null, getter, setter); } /** * 根据Class、字段别名、Field、getter和setter方法生成 Attribute 对象。 Field、tgetter、setter不能同时为null * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldalias 字段别名 * @param field 字段 * @param getter getter方法 * @param setter setter方法 * * @return Attribute对象 */ public static Attribute create(final Class clazz, String fieldalias, final java.lang.reflect.Field field, java.lang.reflect.Method getter, java.lang.reflect.Method setter) { return create(clazz, fieldalias, null, field, getter, setter); } /** * 根据Class、字段别名、字段类型生成虚构的 Attribute 对象,get、set方法为空方法。 * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldalias 字段别名 * @param fieldtype 字段的类 * * @return Attribute对象 */ public static Attribute create(final Class clazz, String fieldalias, final Class fieldtype) { return create(clazz, fieldalias, fieldtype, null, null, null); } /** * 根据Class、字段别名、字段类型、Field、getter和setter方法生成 Attribute 对象。 fieldalias/fieldtype、Field、tgetter、setter不能同时为null. * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldalias 字段别名 * @param fieldtype 字段类型 * @param field 字段 * @param getter getter方法 * @param setter setter方法 * * @return Attribute对象 */ @SuppressWarnings("unchecked") public static Attribute create(final Class clazz, String fieldalias, final Class fieldtype, final java.lang.reflect.Field field, java.lang.reflect.Method getter, java.lang.reflect.Method setter) { if (fieldalias != null && fieldalias.isEmpty()) fieldalias = null; int mod = field == null ? java.lang.reflect.Modifier.STATIC : field.getModifiers(); if (field != null && !java.lang.reflect.Modifier.isStatic(mod) && !java.lang.reflect.Modifier.isPublic(mod)) { Class t = field.getType(); char[] fs = field.getName().toCharArray(); fs[0] = Character.toUpperCase(fs[0]); String mn = new String(fs); if (getter == null) { String prefix = t == boolean.class || t == Boolean.class ? "is" : "get"; try { getter = clazz.getMethod(prefix + mn); } catch (Exception ex) { } } if (setter == null) { try { setter = clazz.getMethod("set" + mn, field.getType()); } catch (Exception ex) { } } } final java.lang.reflect.Field tfield = field == null ? null : (!java.lang.reflect.Modifier.isPublic(mod) || java.lang.reflect.Modifier.isStatic(mod) ? null : field); final java.lang.reflect.Method tgetter = getter; final java.lang.reflect.Method tsetter = setter; if (fieldalias == null) { if (field != null) { fieldalias = field.getName(); } else { String s = null; if (getter != null) { s = getter.getName().substring(getter.getName().startsWith("is") ? 2 : 3); } else if (setter != null) { s = setter.getName().substring(3); } if (s != null) { char[] d = s.toCharArray(); if (d.length < 2 || Character.isLowerCase(d[1])) { d[0] = Character.toLowerCase(d[0]); } fieldalias = new String(d); } } } if (fieldalias == null && fieldtype == null && tgetter == null && tsetter == null && tfield == null) { throw new RuntimeException("[" + clazz + "]have no public field or setter or getter"); } final String fieldname = fieldalias; Class column = fieldtype; if (tfield != null) { // public tfield column = tfield.getType(); } else if (tgetter != null) { column = tgetter.getReturnType(); } else if (tsetter != null) { column = tsetter.getParameterTypes()[0]; } else if (fieldtype == null) { throw new RuntimeException("[" + clazz + "]have no public field or setter or getter"); } final Class pcolumn = column; if (column.isPrimitive()) column = java.lang.reflect.Array.get(java.lang.reflect.Array.newInstance(column, 1), 0).getClass(); final String supDynName = Attribute.class.getName().replace('.', '/'); final String interName = clazz.getName().replace('.', '/'); final String columnName = column.getName().replace('.', '/'); final String interDesc = Type.getDescriptor(clazz); final String columnDesc = Type.getDescriptor(column); ClassLoader loader = Thread.currentThread().getContextClassLoader(); String newDynName = supDynName + "_Dyn_" + clazz.getSimpleName() + "_" + fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array"); if (String.class.getClassLoader() != clazz.getClassLoader()) { loader = clazz.getClassLoader(); newDynName = interName + "_Dyn" + Attribute.class.getSimpleName() + "_" + fieldname.substring(fieldname.indexOf('.') + 1) + "_" + pcolumn.getSimpleName().replace("[]", "Array"); } try { return (Attribute) loader.loadClass(newDynName.replace('/', '.')).getDeclaredConstructor().newInstance(); } catch (Throwable ex) { } //--------------------------------------------------- final ClassWriter cw = new ClassWriter(COMPUTE_FRAMES); 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}); { //构造方法 mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); mv.visitVarInsn(ALOAD, 0); mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); mv.visitInsn(RETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { //field 方法 mv = cw.visitMethod(ACC_PUBLIC, "field", "()Ljava/lang/String;", null, null); mv.visitLdcInsn(fieldname); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { //type 方法 mv = cw.visitMethod(ACC_PUBLIC, "type", "()Ljava/lang/Class;", null, null); if (pcolumn == boolean.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == byte.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == char.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == short.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == int.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == float.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == long.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;"); } else if (pcolumn == double.class) { mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;"); } else { mv.visitLdcInsn(Type.getType(pcolumn)); } 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)); mv.visitInsn(ARETURN); mv.visitMaxs(1, 1); mv.visitEnd(); } { //get 方法 mv = cw.visitMethod(ACC_PUBLIC, "get", "(" + interDesc + ")" + columnDesc, null, null); int m = 1; if (tgetter == null) { if (tfield == null) { mv.visitInsn(ACONST_NULL); } else { //public tfield mv.visitVarInsn(ALOAD, 1); mv.visitFieldInsn(GETFIELD, interName, tfield.getName(), Type.getDescriptor(pcolumn)); if (pcolumn != column) { mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false); m = 2; } } } else { mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, interName, tgetter.getName(), Type.getMethodDescriptor(tgetter), false); if (pcolumn != column) { mv.visitMethodInsn(INVOKESTATIC, columnName, "valueOf", "(" + Type.getDescriptor(pcolumn) + ")" + columnDesc, false); m = 2; } } mv.visitInsn(ARETURN); mv.visitMaxs(m, 2); mv.visitEnd(); } { //set 方法 mv = cw.visitMethod(ACC_PUBLIC, "set", "(" + interDesc + columnDesc + ")V", null, null); int m = 2; if (tsetter == null) { if (tfield == null || java.lang.reflect.Modifier.isFinal(tfield.getModifiers())) { m = 0; } else { //public tfield mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); if (pcolumn != column) { try { java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value"); mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false); m = 3; } catch (Exception ex) { throw new RuntimeException(ex); //不可能会发生 } } mv.visitFieldInsn(PUTFIELD, interName, tfield.getName(), Type.getDescriptor(pcolumn)); } } else { mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); if (pcolumn != column) { try { java.lang.reflect.Method pm = column.getMethod(pcolumn.getSimpleName() + "Value"); mv.visitMethodInsn(INVOKEVIRTUAL, columnName, pm.getName(), Type.getMethodDescriptor(pm), false); m = 3; } catch (Exception ex) { throw new RuntimeException(ex); //不可能会发生 } } mv.visitMethodInsn(INVOKEVIRTUAL, interName, tsetter.getName(), Type.getMethodDescriptor(tsetter), false); } mv.visitInsn(RETURN); mv.visitMaxs(m, 3); mv.visitEnd(); } { //虚拟get mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "get", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, interName); mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "get", "(" + interDesc + ")" + columnDesc, false); mv.visitInsn(ARETURN); mv.visitMaxs(2, 2); mv.visitEnd(); } {//虚拟set mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", null, null); mv.visitVarInsn(ALOAD, 0); mv.visitVarInsn(ALOAD, 1); mv.visitTypeInsn(CHECKCAST, interName); mv.visitVarInsn(ALOAD, 2); mv.visitTypeInsn(CHECKCAST, columnName); mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "set", "(" + interDesc + columnDesc + ")V", false); mv.visitInsn(RETURN); mv.visitMaxs(3, 3); mv.visitEnd(); } cw.visitEnd(); byte[] bytes = cw.toByteArray(); Class creatorClazz = (Class) new ClassLoader(loader) { public final Class loadClass(String name, byte[] b) { return defineClass(name, b, 0, b.length); } }.loadClass(newDynName.replace('/', '.'), bytes); try { return creatorClazz.getDeclaredConstructor().newInstance(); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * 根据Class、字段名、字段类型、getter和setter方法生成 Attribute 对象。 clazz、fieldname、fieldtype都不能为null * * @param 依附类的类型 * @param 字段类型 * @param clazz 指定依附的类 * @param fieldname 字段名 * @param fieldtype 字段类型 * @param getter getter方法 * @param setter setter方法 * * @return Attribute对象 */ public static Attribute create(final Class clazz, final String fieldname, final Class fieldtype, final Function getter, final BiConsumer setter) { Objects.requireNonNull(clazz); Objects.requireNonNull(fieldname); Objects.requireNonNull(fieldtype); return new Attribute() { @Override public Class type() { return fieldtype; } @Override public Class declaringClass() { return clazz; } @Override public String field() { return fieldname; } @Override public F get(T obj) { return getter == null ? null : getter.apply(obj); } @Override public void set(T obj, F value) { if (setter != null) setter.accept(obj, value); } }; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy