@[TOC]

聊聊mybatis的反射之对象工厂

ObjectFactory是对象工厂接口,mybatis可以使用ObjectFactory创新需要的新的对象,默认实现类是DefaultObjectFactory,它主要实现ObjectFactory接口的create方法,

DefaultObjectFactory默认对象工厂类

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

  /**
   * 创建类的实例
   * @param type 要创建实例的类
   * @param constructorArgTypes 构造方法入参类型
   * @param constructorArgs 构造方法入参
   * @param <T> 实例类型
   * @return 创建的实例
   */
  private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    try {
      // 构造方法
      Constructor<T> constructor;
      if (constructorArgTypes == null || constructorArgs == null) { // 参数类型列表为null或者参数列表为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);
    }
  }

通过源码我们能看到,create()方法调用instantiateClass()方法来创建类实例,具体过程就是根据传入的参数选择不同的构造方法来进行实例化对象,如果没有传入参数就使用无参构造器,传入了参数就使用有参构造器

property包

property包有三个类:PropertyCopier,PropertyNamer和PropertyTokenizer

PropertyCopier

PropertyCopier是一个工具类,主要是属性的复制,核心方法copyBeanProperties(),完成对象的输出拷贝功能

PropertyCopier

PropertyNamer类是属性名称的处理器,它的主要功能是把方法名转换为属性名,还有判断这个方法是不是getter或setter方法

PropertyTokenizer

PropertyTokenizer是用来属性解析的,比如传入student[index].name,它能解析出student,index,student[index],name

总结

这篇文章主要介绍了ObjectFactory对象工厂接口和它的实现类DefaultObjectFactory,功能就是根据参数调用适合的构造器生成对象,然后介绍了一下property文件夹下的三个类:PropertyCopier是用来进行属性复制的工具类,PropertyNamer是属性名称处理器,主要实现将方法名转为属性名,PropertyTokenizer是属性的解析类