• Mybatis基础支持层-反射模块:ObjectFactory/Property工具类


    Mybatis基础支持层-反射04:ObjectFactory/Property工具类

    一、ObjectFactory

    public interface ObjectFactory {
    
      /**
      设置参数
       */
      void setProperties(Properties properties);
    
      /**
      根据class 创建一个无参构造类
       */
      <T> T create(Class<T> type);
    
      /**
      根据class 创建一个指定参数的类
       */
      <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
    
      /**
      判断是否为Collection集合
       */
      <T> boolean isCollection(Class<T> type);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    DefaultObjectFactory

    • Mybatis给出了一个默认的实现
    public class DefaultObjectFactory implements ObjectFactory, Serializable {
    
      private static final long serialVersionUID = -8855120656740914948L;
    
      @Override
      public <T> T create(Class<T> type) {
          //调用create创建一个无参构造类
        return create(type, null, null);
      }
    
      @SuppressWarnings("unchecked")
      @Override
      public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        Class<?> classToCreate = resolveInterface(type);
        // we know types are assignable
        //实例化类
        return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
      }
    
      @Override
      public void setProperties(Properties properties) {
        // no props for default
      }
    
    //实例化类的核心方法
      private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
        try {
          Constructor<T> constructor;
          //如果无参
          if (constructorArgTypes == null || constructorArgs == null) {
              //获得一个构造函数
            constructor = type.getDeclaredConstructor();
            try {
                //通过构造函数创建实例
              return constructor.newInstance();
            } catch (IllegalAccessException e) {
              if (Reflector.canControlMemberAccessible()) {
                constructor.setAccessible(true);
                return constructor.newInstance();
              } else {
                throw e;
              }
            }
          }
          //如果包含参数
          constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[constructorArgTypes.size()]));
          try {
              //给出参数数组,构建实例
            return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
          } catch (IllegalAccessException e) {
            if (Reflector.canControlMemberAccessible()) {
              constructor.setAccessible(true);
              return constructor.newInstance(constructorArgs.toArray(new Object[constructorArgs.size()]));
            } else {
              throw e;
            }
          }
        } catch (Exception e) {
          String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
              .stream().map(Class::getSimpleName).collect(Collectors.joining(","));
          String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
              .stream().map(String::valueOf).collect(Collectors.joining(","));
          throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
        }
      }
    
    //指定具体的参数类型
      protected Class<?> resolveInterface(Class<?> type) {
        Class<?> classToCreate;
        if (type == List.class || type == Collection.class || type == Iterable.class) {
          classToCreate = ArrayList.class;
        } else if (type == Map.class) {
          classToCreate = HashMap.class;
        } else if (type == SortedSet.class) { // issue #510 Collections Support
          classToCreate = TreeSet.class;
        } else if (type == Set.class) {
          classToCreate = HashSet.class;
        } else {
          classToCreate = type;
        }
        return classToCreate;
      }
    
      @Override
      public <T> boolean isCollection(Class<T> type) {
          //看type是否是Collection的子类来判断是否是集合
        return Collection.class.isAssignableFrom(type);
      }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 如需一些定制化的配置,比如类的初始化做一些配置,都可定制化ObjectFactory

    二、Property工具集

    在反射模块主要用到的三个属性工具类:PropertyTokenizer,PropertyNamer,PropertyCopier

    PropertyTokenizer

    • 解析item[0].name这些由"." “[]” 符号组成的表达式
    //实现Iterator接口,标识这个类能够迭代使用,可以解析多层[[[].x].xx].xxx的场景
    public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
      private String name;
      private final String indexedName;
      private String index;
      private final String children;
    
      public PropertyTokenizer(String fullname) {
        int delim = fullname.indexOf('.');
        //是否包含.
        if (delim > -1) {
            //包含.
            //获取参数的key
          name = fullname.substring(0, delim);
          //获取参数的value
          children = fullname.substring(delim + 1);
        } else {
            //不包含.
          name = fullname;
          children = null;
        }
        indexedName = name;
        delim = name.indexOf('[');
        //参数的key是否包含[]
        if (delim > -1) {
            //包含
            //索引位置
          index = name.substring(delim + 1, name.length() - 1);
          //参数真实key
          name = name.substring(0, delim);
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    PropertyNamer

    • 提供静态方法帮助完成方法名到属性名的转换,并作检测
    public final class PropertyNamer {
    
      private PropertyNamer() {
        // Prevent Instantiation of Static Class
      }
    
      public static String methodToProperty(String name) {
          //方法为isXXX
        if (name.startsWith("is")) {
            //去除is,获取属性名称
          name = name.substring(2);
        } else if (name.startsWith("get") || name.startsWith("set")) {//方法为getXXX setXXX
        //去除get set 获取属性名称
          name = name.substring(3);
        } else {
          throw new ReflectionException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
        }
    //将isXxx getXxx setXxx的驼峰大写改为小写
        if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
          name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
        }
    
        return name;
      }
    
      public static boolean isProperty(String name) {
        return name.startsWith("get") || name.startsWith("set") || name.startsWith("is");
      }
    
      public static boolean isGetter(String name) {
        return name.startsWith("get") || name.startsWith("is");
      }
    
      public static boolean isSetter(String name) {
        return name.startsWith("set");
      }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    PropertyCopier

    • 属性拷贝类工具,实现相同类型的对象之间属性的值拷贝
    public final class PropertyCopier {
    
      private PropertyCopier() {
        // Prevent Instantiation of Static Class
      }
    
      public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
        Class<?> parent = type;
        while (parent != null) {
            //获取类的属性列表
          final Field[] fields = parent.getDeclaredFields();
          for (Field field : fields) {
            try {
              try {
                  //设置目标对象的字段 为源对象对应字段的值
                field.set(destinationBean, field.get(sourceBean));
              } catch (IllegalAccessException e) {
                if (Reflector.canControlMemberAccessible()) {
                  field.setAccessible(true);
                  field.set(destinationBean, field.get(sourceBean));
                } else {
                  throw e;
                }
              }
            } catch (Exception e) {
              // Nothing useful to do, will only fail on final fields, which will be ignored.
            }
          }
          parent = parent.getSuperclass();
        }
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
  • 相关阅读:
    TCP 时间戳妙用
    谷歌浏览器 ERR_MANDATORY_PROXY_CONFIGURATION_FAILED 报错的处理方式
    Redis常用命令和Java操作Redis教程
    关于Spring Data MongoDB SpEL表达式注入漏洞(CVE-2022-22980)的预警提示
    代码随想录 | Day7
    J2EE项目部署与发布(Windows版本)
    打印机多张双面打印使用说明
    SpringBoot + layui 框架实现一周免登陆功能
    追寻红色记忆、晋国文明之思考毕业季研学营
    clang插件对llvm源码插桩,分析函数调用日志(1)
  • 原文地址:https://blog.csdn.net/c_zyer/article/details/126309270