MyBatis 源码的深入剖析:本质与核心特性

下面是对 MyBatis 源码的深入剖析,重点围绕其 本质与核心特性 展开详细解析。通过理解 MyBatis 的设计思想、架构组成和运行机制,你将掌握它为何能在持久层框架中占据重要地位。


🔍 一、MyBatis 的本质

✅ 一句话定义:

MyBatis 是一个“半自动化”的持久层框架,本质是 JDBC 的增强工具,它封装了 JDBC 的重复代码,同时保留 SQL 的完全控制权。

🧠 与“全自动”ORM框架(如 Hibernate)对比:

特性MyBatisHibernate
SQL 控制手写 SQL,完全可控自动生成 SQL,灵活性差
学习成本低,贴近 JDBC高,需掌握 HQL 和映射规则
性能优化易于调优(可写复杂 SQL)受限于生成的 SQL
自动化程度半自动(手动写 SQL + 自动映射结果)全自动(对象 ↔ 表 自动映射)

💡 所以:MyBatis 的本质是“SQL 映射框架”,而不是传统意义上的 ORM 框架。


🏗️ 二、MyBatis 的核心特性

1. SQL 与代码分离(解耦)

  • SQL 写在 XML 文件或注解中,与 Java 代码解耦。
  • 支持动态 SQL(<if>, <choose>, <foreach> 等),灵活构建查询。
<select id="findUserById" resultType="User">
  SELECT * FROM user WHERE id = #{id}
  <if test="name != null">
    AND name LIKE CONCAT('%', #{name}, '%')
  </if>
</select>

2. 自动映射(Result Mapping)

  • 将查询结果自动映射为 Java 对象(POJO)。
  • 支持 resultType(简单类型)和 resultMap(复杂关系,如一对多、嵌套对象)。
<resultMap id="userMap" type="User">
  <id property="id" column="user_id"/>
  <result property="name" column="user_name"/>
  <association property="role" javaType="Role" resultMap="roleMap"/>
</resultMap>

3. 动态 SQL

  • 使用 OGNL 表达式 + XML 标签动态拼接 SQL。
  • 避免手动拼接字符串,防止 SQL 注入,提升可维护性。

4. 插件机制(Interceptor)

  • 提供 Executor, StatementHandler, ParameterHandler, ResultSetHandler 四大接口的拦截能力。
  • 可实现分页、日志、性能监控、数据加密等通用功能。
@Intercepts({@Signature(type = Executor.class, method = "query", args = { ... })})
public class MyPlugin implements Interceptor {
    public Object intercept(Invocation invocation) {
        // 拦截执行逻辑
    }
}

5. 缓存机制(一级 & 二级缓存)

  • 一级缓存:基于 SqlSession 的会话级缓存,默认开启。
  • 二级缓存:基于 namespace(Mapper 接口)的跨会话缓存,需手动开启。
<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

⚠️ 注意:二级缓存可能导致脏读,高并发下建议使用 Redis 替代。

6. 灵活的配置方式

  • 支持 XML 配置 和 注解 两种方式。
  • 可与 Spring 集成,通过 @MapperScan 自动注册 Mapper 接口。

🧩 三、MyBatis 核心组件架构图(源码视角)

+---------------------+
|   SqlSessionFactory  | ← 通过 SqlSessionFactoryBuilder 构建
+----------+----------+
           |
           | openSession()
           v
+---------------------+
|     SqlSession       | ← 线程不安全,每次请求应创建新实例
+----------+----------+
           |
           | getMapper(UserMapper.class)
           v
+---------------------+
|     Mapper Proxy     | ← JDK 动态代理生成接口实现
+----------+----------+
           |
           | execute()
           v
+---------------------+
|   Executor (执行器)   | ← SimpleExecutor, ReuseExecutor, BatchExecutor
           |
           | 拦截(可被插件增强)
           v
+---------------------+
| StatementHandler    | ← 处理 PreparedStatement / CallableStatement
+----------+----------+
           |
           v
+---------------------+
| ParameterHandler    | ← 设置 SQL 参数
+----------+----------+
           |
           v
+---------------------+
| ResultSetHandler    | ← 处理结果集映射
+---------------------+

🔧 四、MyBatis 源码核心流程剖析

1. 初始化阶段(构建 SqlSessionFactory

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
  • 解析 mybatis-config.xml:使用 XPathParser 解析全局配置。
  • 解析 Mapper.xml:注册 MappedStatement(封装 SQL、参数、返回类型等)。
  • 生成 Configuration 对象:保存所有配置信息,是 MyBatis 的“大脑”。

📌 源码入口:XMLConfigBuilder.parse()


2. 获取 SqlSession(执行会话)

SqlSession session = sqlSessionFactory.openSession();
  • 创建 Executor(根据 isCommitisReadOnly 等选择类型)。
  • 封装 Transaction(事务管理器)。
  • 返回 DefaultSqlSession 实例。

3. 获取 Mapper 接口代理对象

UserMapper mapper = session.getMapper(UserMapper.class);
  • 使用 MapperProxyFactory 创建 JDK 动态代理。
  • 代理逻辑由 MapperProxy 实现,拦截所有方法调用。

📌 关键类:MapperProxy, MapperMethod


4. 执行 SQL(方法调用触发)

User user = mapper.findUserById(1);
执行流程:
  1. MapperProxy.invoke() → 找到对应的 MapperMethod
  2. MapperMethod.execute() → 根据 SQL 类型(SELECT/INSERT/UPDATE/DELETE)调用 sqlSession.selectOne()
  3. SimpleExecutor.query() → 经过缓存检查
  4. StatementHandler.prepare() → 创建 PreparedStatement
  5. ParameterHandler.setParameters() → 设置参数
  6. StatementHandler.query() → 执行 SQL
  7. ResultSetHandler.handleResultSets() → 映射结果集 → 返回 User

🌟 五、MyBatis 的设计亮点(源码级理解)

设计模式应用场景说明
建造者模式SqlSessionFactoryBuilder构建复杂的 SqlSessionFactory
工厂模式ObjectFactory, DataSourceFactory创建对象和数据源
代理模式MapperProxy动态生成 Mapper 接口实现
模板方法模式BaseExecutor定义执行流程,子类实现差异逻辑
责任链模式Interceptor 插件链多个插件依次拦截处理
适配器模式TypeHandler将 Java 类型与 JDBC 类型适配

📈 六、MyBatis 的适用场景

推荐使用场景

  • 需要精细控制 SQL(如复杂查询、分页、多表联查)
  • 已有数据库,需反向工程(数据库优先开发)
  • 性能敏感系统(可优化每一条 SQL)
  • 团队熟悉 SQL,追求灵活性

不推荐场景

  • 快速原型开发(不如 JPA 快)
  • 数据库频繁变更(XML 维护成本高)
  • 完全不想写 SQL

🧰 七、MyBatis Plus 与原生 MyBatis 对比

特性MyBatisMyBatis Plus
CRUD 操作需写 SQL提供 IService 自动生成
分页手动写分页 SQL 或插件内置分页插件
条件构造原生 SQL提供 QueryWrapper
代码生成提供代码生成器
本质SQL 映射框架MyBatis 增强工具

💡 MyBatis Plus 是 MyBatis 的“增强版”,但核心仍是 MyBatis。


✅ 总结:MyBatis 的本质与价值

维度说明
本质JDBC 的轻量级封装,SQL 映射框架
核心价值让开发者专注于 SQL,同时享受 ORM 的便利
设计理念“不要试图隐藏 SQL,而是更好地管理它”
源码启示简洁、解耦、扩展性强,是学习 Java 框架设计的优秀范本

📚 延伸学习建议

  1. 阅读源码起点

    • SqlSessionFactoryBuilder.build()
    • XMLMapperBuilder.parse()
    • MapperProxy.invoke()
    • SimpleExecutor.query()
  2. 调试建议

    • 使用 Debug 跟踪 mapper.selectList() 的完整调用链。
    • 自定义 Interceptor 观察四大对象的拦截时机。
  3. 推荐书籍

    • 《MyBatis 技术内幕》—— 深入源码分析
    • 《Java 持久层框架:MyBatis 设计与实现》
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值