mybatis基础支持层-反射模块-03

ObjectFactory/Property工具类

Posted by Claire on June 13, 2020

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);

}

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);
  }

}

  • 如需一些定制化的配置,比如类的初始化做一些配置,都可定制化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);
    }
  }

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");
  }

}

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();
    }
  }

}