Mybatis工具—对象工厂(ObjectFactory)

  ObjectFactory是一个定义了创建新对象的接口,即如其名称得上是一个对象工厂。Mybatis每次在创建Mapper映射结果对象实例的时候,就会使用ObjectFactory来完成对象实例。其接口在Mybatis源代码中只有一个默认的实现,即DefaultObjectFactory。
  DefaultObjectFactory实现了ObjectFactory接口定义的所有API。

ObjectFactory objectFactory = new DefaultObjectFactory();
List<String> list = objectFactory.create(List.class);
Robot robot = objectFactory.create(Robot.class);

  如上述示例代码所示,使用ObjectFactory来创建对象实例是一件相当轻松的事情,首先通过DefaultObjectFactory的构造方法构造一个ObjectFactory对象,然后调用对应的create方法,就可以创建一个对象实例。

对象实例的创造者

  通过示例代码能看出,通过ObjectFactory的create方法能创建对象实例,接下来看看create方法的源代码细则。

@Override
public <T> T create(Class<T> type) {
    return create(type, null, null);
}

/**
 * @param type                  想要创建的对象
 * @param constructorArgTypes   构造方法中参数的类型
 * @param constructorArgs	    构造方法中参数的值
 */ 
@SuppressWarnings("unchecked")
@Override
public <T> T create(
        Class<T> type, 
        List<Class<?>> constructorArgTypes, 
        List<Object> constructorArgs) {
    // 解析接口类型
    Class<?> classToCreate = resolveInterface(type);
    // 实例化对象
    return (T) instantiateClass(
        classToCreate, constructorArgTypes, constructorArgs);
}

  源代码中的create方法一共做了两件事,一是解析type对应的接口类型,获取接口对应的实现类,一是通过所传入的构造方法中的constructorArgTypes(类型)和constructorArgs(值)来实例化type对象。

解析接口类型

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

  resolveInterface是对象实例化的第一步,源代码显示,如果想要实例化的接口是List或Collection亦或Iterable,那么对应的实现类是ArrayList;如果想要实例化的接口是Map,那么对应的实现类是HashMap;如果想要实例化的接口是SortedSet,那么对应的实现类是TreeSet;如果想要实例化的接口是Set,那么对应的实现类是HashSet。

实例化对象

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[0]));
      try {
        // 通过构造方法和参数值实例化对象  
        return constructor.newInstance(constructorArgs.toArray(new Object[0]));
      } catch (IllegalAccessException e) {
        if (Reflector.canControlMemberAccessible()) {
          constructor.setAccessible(true);
          return constructor.newInstance(constructorArgs.toArray(new Object[0]));
        } 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);
    }
}

  instantiateClass的源代码相对长一点,但是整篇源代码中只做了两件事,一是判断所传入的constructorArgTypes(类型)和constructorArgs(值)是否为空,如果为空,就直接获取对应的构造方法,然后再实例化对象;如果不为空,则先根据constructorArgTypes所传的参数类型获取待实例化对象带参数的构造方法,然后再使用constructorArgs来实例化对象。其余剩下的源代码就是当发现异常时的处理操作。

自定义ObjectFactory

  Mybatis之所以在创建Mapper映射结果对象的时候使用ObjectFactory,主要是为了给Mybatis的使用者提供一个扩展机制,以应对使用者在创建对象实例时候的一些特殊逻辑,如将某个业务编码织入到某个特定的对象中。
  注:如果通过继承DefaultObjectFactory类的方法来实现了自定义的ObjectFactory,那么就得使用Mybatis提供的标签来注册自定义的ObjectFactory。

<objectFactory type="">
  <property name="" value=""/>
</objectFactory>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐只乐之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值