跳至主要內容

Mybatis 源码学习-全流程图解读

科哒大约 3 分钟


一、案例背景说明

业务场景:通过用户ID查询用户信息
涉及对象

  • User类(POJO,含id, name, age字段)
  • UserMapper接口(定义selectUserById方法)
  • UserMapper.xml(含SQL映射配置)

二、全流程分步解读(结合源码)

阶段1:配置初始化

📁 配置文件加载

<!-- mybatis-config.xml -->
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="UserMapper.xml"/>
  </mappers>
</configuration>

🔧 关键源码节点

  • XMLConfigBuilder:解析XML配置文件(核心方法parseConfiguration()
  • Configuration:全局配置容器(存储environments、mappedStatements等)
  • SqlSessionFactoryBuilder:通过build()方法生成SqlSessionFactory
// 源码路径:org.apache.ibatis.session.SqlSessionFactoryBuilder
public SqlSessionFactory build(InputStream inputStream) {
  XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, null, null);
  return build(parser.parse()); // 最终生成DefaultSqlSessionFactory
}

阶段2:会话创建

🚪 SqlSession创建流程

// 应用层代码
SqlSession sqlSession = sqlSessionFactory.openSession();

🔧 源码执行链路

  1. DefaultSqlSessionFactory.openSession()
    • TransactionFactory获取Transaction对象(JDBC事务)
    • 创建Executor执行器(根据配置选择SIMPLE/REUSE/BATCH模式)
  2. Executor层级结构

阶段3:Mapper代理绑定

🎯 接口方法调用

UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);

🔧 动态代理机制

  • MapperProxy(JDK动态代理核心类)
// 源码路径:org.apache.ibatis.binding.MapperProxy
public Object invoke(Object proxy, Method method, Object[] args) {
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args); // 路由到SQL执行
}
  • MappedStatement:存储SQL映射元数据(SQL类型、参数映射、结果映射)

阶段4:SQL执行引擎

⚙️ 执行器工作流(以PreparedStatement为例):

  1. StatementHandler创建
    • RoutingStatementHandler根据Statement类型路由到具体实现
    • PreparedStatementHandler处理参数化SQL
  2. 参数处理
// 源码片段:DefaultParameterHandler.setParameters()
for (ParameterMapping pm : parameterMappings) {
  Object value = metaObject.getValue(pm.getProperty());
  typeHandler.setParameter(ps, i, value, jdbcType);
}
- **ParameterHandler**:通过`TypeHandler`转换Java对象到JDBC参数
  1. SQL执行
// 源码路径:SimpleExecutor.doQuery()
Statement stmt = prepareStatement(handler, log);
return handler.query(stmt, resultHandler);

阶段5:结果集映射

📊 结果处理流程

  1. ResultSetHandler
    • 使用ResultMap解析映射规则
    • 通过反射构建POJO对象
  2. 嵌套对象处理(源码示例):
// DefaultResultSetHandler.createResultObject()
if (resultMap.hasNestedResultMaps()) {
  return createNestedResultObject(rsw, resultMap, columnPrefix);
} else {
  return createPlainResultObject(rsw, resultMap, columnPrefix);
}

三、核心设计模式解析

设计模式应用场景对应组件/源码
工厂模式SqlSession创建SqlSessionFactory/DefaultSqlSessionFactory
动态代理Mapper接口实现MapperProxy/MapperProxyFactory
模板方法执行流程标准化BaseExecutor中的doQuery模板
责任链模式插件拦截机制InterceptorChain
建造者模式配置对象构建XMLConfigBuilder/XMLMapperBuilder

四、全流程可视化总结


五、调试学习建议

  1. 关键断点位置
    • MapperProxy.invoke():跟踪接口方法调用
    • SimpleExecutor.doQuery():观察SQL执行过程
    • DefaultResultSetHandler.handleResultSets():分析结果映射
  2. 日志配置
<configuration>
  <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
  </settings>
</configuration>

通过此案例可完整跟踪MyBatis从配置加载到结果返回的全链路过程,建议结合IDEA的Debug功能逐层分析各组件协作关系。

  1. 源码案例Test

如果想深入理解某些功能点,也可以对源码的案例进行Debug分析,加深某些功能的理解。