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创建实体类实例的最终执行者!

相关推荐
杨运交17 小时前
[022][数据模块]基于雪花算法的 MyBatis-Plus 主键生成器设计与实现
mybatis
Mahir0819 小时前
MyBatis 深度解密:从执行流程到底层原理全解
java·后端·面试·mybatis
Mahir081 天前
MyBatis 分页与插件深度解密:从插件机制到三大分页方案原理全解
java·后端·mybatis·mybatis-plus·大厂面试题
Apache RocketMQ1 天前
全新 AI 消息模型:Apache RocketMQ 如何让 AI 应用拥抱事件驱动架构?
人工智能·apache·rocketmq
谷哥的小弟1 天前
图文详解Spring Boot整合MyBatisPlus(附源码)
mybatis·源码·springboot·mybatis-plus·整合
MageGojo1 天前
给起名工具接入八字起名 API:参数设计、JSON 示例和应用场景
json·apache
醉颜凉1 天前
Lucene底层原理:倒排索引实现原理与代码实战,彻底吃透搜索引擎核心
搜索引擎·mybatis·lucene
JAVA面经实录9172 天前
MyBatis学习体系
java·mybatis
墨_风2 天前
MyBatis时间区间查询异常排查(达梦数据库)
数据库·mybatis·达梦
霸道流氓气质2 天前
MyBatis 分页查询 + Feign 数据补充实战指南
数据库·oracle·mybatis