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

相关推荐
脑电信号要分类7 小时前
将多张图片拼接成一个pdf文件输出
pdf·c#·apache
计算机学姐9 小时前
基于SpringBoot的校园二手书籍交易系统【个性化推荐+数据可视化统计+我买到的+我卖出的】
vue.js·spring boot·后端·mysql·信息可视化·intellij-idea·mybatis
zjneymar10 小时前
Mybatis的动态sql
java·sql·mybatis
不是书本的小明10 小时前
Apache vs Nginx vs Tomcat 核心区别与优化
nginx·tomcat·apache
稻草猫.11 小时前
MyBatis-Plus高效开发全攻略
java·数据库·后端·spring·java-ee·mybatis·mybatis-plus
计算机学姐12 小时前
基于SpringBoot的网吧管理系统
java·spring boot·后端·spring·tomcat·intellij-idea·mybatis
弹简特12 小时前
【JavaEE20-后端部分】 MyBatis 入门第四篇:多表查询、#{}与${}详解、数据库连接池
数据库·mybatis
哆啦A梦158821 小时前
Springboot整合MyBatis实现数据库操作
数据库·spring boot·mybatis
弹简特1 天前
【JavaEE19-后端部分】 MyBatis 入门第三篇:使用XML完成增删改查
xml·mybatis
小江的记录本1 天前
【VO、DTO、Entity】VO、DTO、Entity三大核心数据对象全解析(附核心对比表 + 代码示例)
java·数据库·spring boot·spring·架构·mybatis·数据库架构