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

相关推荐
zhongben_keji1 天前
家政小程序开发全解:经营模式、品类矩阵、派单约束与信用核验
线性代数·矩阵·apache
正儿八经的少年1 天前
MyBatis 一对一、一对多 SQL
数据库·sql·mybatis
paopaokaka_luck2 天前
社区服务平台(加权协同过滤推荐、Jieba中文词频分析、WebSocket实时聊天、求助处理闭环、 活动积分闭环、ECharts多维分析)
java·前端·spring boot·mysql·echarts·mybatis
weixin_177297220692 天前
二手旧物回收小程序先要解决的不是下单,是“上门之后价格变了怎么办“
小程序·apache
努力变的更好2 天前
H5与小程序之间的回调
前端·小程序·apache
代码不停3 天前
MyBatis操作数据库
数据库·mybatis
wno7043 天前
Spring Boot中JdbcTemplate与Mybatis使用PostgreSQL
spring boot·postgresql·mybatis
lzhdim4 天前
100条常用SQL语句
数据库·sql·mysql·mybatis
景熙55234 天前
2.什么是业务后台系统
java·spring·tomcat·mybatis·jdbc
十碗饭吃不饱4 天前
Apache POI 踩坑:setFontFamily 二次设置字体不生效、样式残留问题深度解析
java·word·apache