MyBatis 与 MyBatis-Plus 底层机制原理深度剖析

MyBatis 与 MyBatis-Plus 底层机制原理深度剖析

MyBatis 与 MyBatis-Plus 底层机制原理深度剖析

本文基于 MyBatis 3.5.x 及 MyBatis-Plus 3.5.5 最新源码与官方文档,结合生产实践,对两条技术栈的启动流程、SQL 执行链路、插件体系、功能增强点做一次性梳理,帮助你在架构选型、性能调优、二次开发时做到“选型有据、调优有数、扩展有方”。

一、MyBatis 底层核心机制

1.1 启动链路:从配置文件到 SqlSession

阶段关键类职责解析配置SqlSessionFactoryBuilder读取 mybatis-config.xml 与 Mapper.xml,构建 Configuration 单例创建工厂SqlSessionFactory基于 Configuration 生成,线程安全会话实例SqlSession每次请求新建,持有 Executor 与一级缓存代理生成MapperProxyFactory使用 JDK 动态代理创建 Mapper 接口实现// 伪代码:启动入口

String resource = "mybatis-config.xml";

InputStream inputStream = Resources.getResourceAsStream(resource);

SqlSessionFactory sqlSessionFactory =

new SqlSessionFactoryBuilder().build(inputStream);

SqlSession session = sqlSessionFactory.openSession();

UserMapper mapper = session.getMapper(UserMapper.class);

1.2 SQL 执行链路

调用 mapper.selectById(1L)

→ MapperProxy.invoke() // 拦截接口调用

→ MapperMethod.execute() // 根据 SQL 类型分发

→ DefaultSqlSession.selectOne() // 打开会话

→ CachingExecutor.query() // 二级缓存

→ SimpleExecutor.doQuery() // 真正 JDBC 执行

→ StatementHandler.prepare() // 创建 Statement

→ ParameterHandler.setParameters() // 绑定参数

→ ResultSetHandler.handleResultSets() // 结果映射

动态 SQL:通过 OGNL + SqlNode 树在运行时拼接 SQL。延迟加载:基于 CGLIB 代理,在第一次访问属性时才触发子查询。缓存:

一级缓存默认开启,生命周期同 SqlSession;二级缓存 mapper 级别,依赖 标签与序列化策略。

二、MyBatis-Plus 的“增强”到底做了哪些事?

MyBatis-Plus 只做“无侵入增强”:在 MyBatis 原有执行链路上,通过 MybatisPlusInterceptor → InnerInterceptor 责任链 追加功能。

2.1 启动差异

维度MyBatisMyBatis-Plus工厂构建手动 SqlSessionFactoryBuilderMybatisPlusAutoConfiguration(Spring Boot Starter)配置注入XML/JavaConfigapplication.yml + MybatisPlusPropertiesMapper 注册 或 @Mapper自动扫描 @Mapper + 内置 BaseMapper2.2 执行链增强点

MyBatis-Plus 执行链路

├─ 分页:PaginationInnerInterceptor

├─ 乐观锁:OptimisticLockerInnerInterceptor

├─ 多租户:TenantLineInnerInterceptor

└─ 数据权限:DataPermissionInterceptor

BaseMapper 原理:在启动时,MyBatis-Plus 会把通用 CRUD 的 XML 模板注入到 Configuration 中,从而无需手写 SQL。条件构造器:QueryWrapper 内部维护 SQLSegments,最终拼成 BoundSql,与手写 SQL 无性能差异。

三、插件机制对比

能力MyBatis InterceptorMyBatis-Plus InnerInterceptor拦截点Executor/ParameterHandler/ResultSetHandler/StatementHandler细化到 willDoQuery / beforeUpdate 等 7 个阶段注册方式 或 @InterceptsMybatisPlusInterceptor.addInnerInterceptor()典型应用自定义分页、审计内置分页、乐观锁、租户隔离示例:统一设置 order_time = create_time

public class TimeSyncInnerInterceptor implements InnerInterceptor {

@Override

public boolean willDoUpdate(Executor executor, MappedStatement ms, Object parameter) {

if (parameter instanceof User) {

User u = (User) parameter;

u.setCreateTime(u.getOrderTime());

}

return true;

}

}

四、性能与可维护性对比

维度MyBatisMyBatis-Plus建议开发效率手写 SQL & XML通用 Mapper + 条件构造器80% 场景优先 Plus灵活性极高中(复杂 SQL 需自定义 SQL)复杂报表仍用 MyBatis批量操作手写 foreachsaveBatch + rewriteBatchedStatementsPlus 性能更优缓存需手动配置 Redis 二级与 MyBatis 保持一致共用策略升级成本低注意版本差异(3.5.x 起 JDK17+)锁定 LTS 版本

五、选型与落地建议

新项目:直接采用 MyBatis-Plus + Spring Boot 3 Starter,90% CRUD 零 SQL。老项目:可渐进式替换:先引入 Plus,保留原有 Mapper,逐步迁移到 BaseMapper。复杂场景:

报表、存储过程 → 继续用 MyBatis XML;多租户、数据权限 → 使用 Plus 插件链 + 自定义 InnerInterceptor。

团队技能:初级团队 Plus 降低门槛;资深团队利用 Plus 插件 SPI 做框架级扩展。

六、小结

MyBatis 是“SQL 引擎”,掌握 XML + 拦截器即可玩出花;MyBatis-Plus 是“生产力工具”,在 MyBatis 之上用 约定大于配置 的思想,把 CRUD、分页、乐观锁等高频需求做成 可插拔组件。

两者并非“取代”,而是 组合使用:MyBatis 负责深度定制,Plus 负责提效。理解底层后,你可以自由地在二者之间“按需切换、无缝增强”。

没有套路,真实资料!

🌟 相关推荐

冰岛为什么进世界杯了
365bet亚洲版体育在线

冰岛为什么进世界杯了

📅 10-09 👀 2178
“神医”刘洪斌:3年换9个身份,坑了老年人80亿,如今下场如何?
优驾怎么样?优驾功能特点详细图文介绍
beat365英超欧冠平台

优驾怎么样?优驾功能特点详细图文介绍

📅 08-07 👀 6171