MyBatis的默认对象工厂org.apache.ibatis.reflection.factory.ObjectFactory

objectFactory.create(resultType) 的实现在MyBatis的默认对象工厂中。让我带你找到具体的源码位置:

1. 接口定义

首先在 org.apache.ibatis.reflection.factory.ObjectFactory 接口中:

java 复制代码
public interface ObjectFactory {
  /**
   * 使用默认构造函数创建对象
   */
  <T> T create(Class<T> type);
  
  // 其他重载方法...
}

2. 默认实现

org.apache.ibatis.reflection.factory.DefaultObjectFactory 中:

java 复制代码
public class DefaultObjectFactory implements ObjectFactory, Serializable {

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

  @Override
  public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    // 1. 解析实际要实例化的类(处理集合接口)
    Class<?> classToCreate = resolveInterface(type);
    
    // 2. 调用具体创建方法
    return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
  }

  private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    try {
      Constructor<T> constructor;
      
      // 3. 如果没有构造函数参数,使用默认构造函数
      if (constructorArgTypes == null || constructorArgs == null) {
        constructor = type.getDeclaredConstructor();
        try {
          // 4. 调用无参构造函数创建实例
          return constructor.newInstance();
        } catch (IllegalAccessException e) {
          // 如果访问受限,设置可访问后重试
          if (Reflector.canControlMemberAccessible()) {
            constructor.setAccessible(true);
            return constructor.newInstance();
          } else {
            throw e;
          }
        }
      }
      
      // 5. 如果有构造函数参数,使用有参构造函数(这是你出错的分支)
      constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
      // ... 有参构造逻辑
      
    } catch (Exception e) {
      // 异常处理
    }
  }
}

3. 关键源码路径

完整的调用栈是:

复制代码
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject()
↓
org.apache.ibatis.reflection.factory.ObjectFactory.create(Class<T> type)
↓
org.apache.ibatis.reflection.factory.DefaultObjectFactory.create(Class<T> type)
↓
org.apache.ibatis.reflection.factory.DefaultObjectFactory.instantiateClass()
↓
java.lang.reflect.Constructor.newInstance()  // 最终调用Java反射API

4. 在你的错误堆栈中的体现

回顾你的错误堆栈:

复制代码
Caused by: org.apache.ibatis.reflection.ReflectionException: 
Error instantiating class cn.wh.dueremind.entity.ExcelImportRecord 
with invalid types (Long,String,String,String,ObjectNode,ObjectNode,ObjectNode,...)

at org.apache.ibatis.reflection.factory.DefaultObjectFactory.instantiateClass(DefaultObjectFactory.java:86)
at org.apache.ibatis.reflection.factory.DefaultObjectFactory.create(DefaultObjectFactory.java:53)

这正好对应:

  • 第86行:DefaultObjectFactory.instantiateClass() 中的有参构造调用
  • 第53行:DefaultObjectFactory.create() 方法

5. 实际执行流程

当你的类有无参构造函数时:

java 复制代码
// MyBatis执行路径:
objectFactory.create(ExcelImportRecord.class)
↓
instantiateClass(ExcelImportRecord.class, null, null)  // 参数为null
↓
constructor = ExcelImportRecord.class.getDeclaredConstructor()  // 获取无参构造
↓
return constructor.newInstance()  // 成功创建实例!

当你的类没有无参构造函数时:

java 复制代码
// MyBatis执行路径:
objectFactory.create(ExcelImportRecord.class)
↓
instantiateClass(ExcelImportRecord.class, constructorArgTypes, constructorArgs)  // 有参数!
↓
// 尝试匹配有参构造函数,但ObjectNode类型不匹配
↓
失败!抛出 ReflectionException

6. 自定义ObjectFactory

你也可以实现自定义的ObjectFactory:

java 复制代码
public class CustomObjectFactory extends DefaultObjectFactory {
  @Override
  public <T> T create(Class<T> type) {
    // 自定义创建逻辑
    if (type == ExcelImportRecord.class) {
      return (T) new ExcelImportRecord();
    }
    return super.create(type);
  }
}

然后在配置中指定:

xml 复制代码
<settings>
  <objectFactory type="com.example.CustomObjectFactory"/>
</settings>

总结

objectFactory.create(resultType) 的核心实现在:

  • 接口org.apache.ibatis.reflection.factory.ObjectFactory
  • 默认实现org.apache.ibatis.reflection.factory.DefaultObjectFactory
  • 关键方法instantiateClass() 中的无参构造调用

这就是MyBatis创建实体类实例的最终执行者!

相关推荐
莫寒清4 天前
Mybatis的插件原理
面试·mybatis
james的分享4 天前
大数据领域核心 SQL 优化框架Apache Calcite介绍
大数据·sql·apache·calcite
莫寒清4 天前
Apache Tika
java·人工智能·spring·apache·知识图谱
归叶再无青4 天前
web服务安装部署、性能升级等(Apache、Nginx)
运维·前端·nginx·云原生·apache·bash
莫寒清4 天前
MyBatis 中动态 SQL 的作用
面试·mybatis
吹晚风吧5 天前
实现一个mybatis插件,方便在开发中清楚的看出sql的执行及执行耗时
java·sql·mybatis
码云数智-大飞5 天前
像写 SQL 一样搜索:dbVisitor 如何用 MyBatis 范式颠覆 ElasticSearch 开发
sql·elasticsearch·mybatis
Mr__Miss5 天前
mybatisPlus分页组件3.5.15版本报错解决方案
mybatis
无名-CODING5 天前
MyBatis中#{}和${}完全指南:从原理到实战
mybatis
忙碌5445 天前
OpenTelemetry实战指南:构建云原生全链路可观测性体系
ios·flink·apache·iphone