MyBatis 底层原理深度解析
一、整体架构设计
MyBatis 采用分层架构设计,核心模块如下:
1. 分层架构
- 接口层:提供API(SqlSession、Mapper接口)
- 核心处理层:SQL解析、参数映射、SQL执行、结果映射
- 基础支撑层:连接管理、事务管理、缓存、日志等
2. 核心组件协作
二、核心组件详解
1. SqlSession
- 作用:MyBatis 核心操作接口
- 实现类:
DefaultSqlSession
- 关键功能:
public interface SqlSession extends Closeable { <T> T selectOne(String statement); <E> List<E> selectList(String statement); int insert(String statement); int update(String statement); int delete(String statement); void commit(); void rollback(); <T> T getMapper(Class<T> type); }
2. Executor(执行器)
-
类型:
SimpleExecutor
:默认执行器(每次请求创建新Statement)ReuseExecutor
:重用预处理StatementBatchExecutor
:批量操作优化CachingExecutor
:二级缓存装饰器
-
执行流程:
public class SimpleExecutor extends BaseExecutor { public <E> List<E> query(...) { Statement stmt = null; try { Configuration config = context.getConfiguration(); // 1. 获取MappedStatement MappedStatement ms = config.getMappedStatement(statement); // 2. 创建StatementHandler StatementHandler handler = config.newStatementHandler(..., ms, ...); // 3. 准备Statement stmt = prepareStatement(handler); // 4. 执行查询 return handler.query(stmt, resultHandler); } finally { closeStatement(stmt); } } }
3. MappedStatement
- 作用:存储SQL映射信息(XML/注解配置的SQL)
- 关键属性:
public final class MappedStatement { private String id; private SqlSource sqlSource; private SqlCommandType sqlCommandType; private Class<?> parameterType; private Class<?> resultType; private ResultMap resultMap; // ... }
4. SqlSource & BoundSql
- SqlSource:SQL源(动态/静态SQL)
DynamicSqlSource
:含动态标签(if/foreach)RawSqlSource
:纯静态SQL
- BoundSql:最终执行的SQL和参数
public class BoundSql { private final String sql; // 解析后的SQL private final List<ParameterMapping> parameterMappings; private final Object parameterObject; // 参数对象 // ... }
三、SQL执行流程深度解析
1. SQL解析过程
2. 参数映射原理
- ParameterHandler:处理参数映射
public class DefaultParameterHandler implements ParameterHandler { public void setParameters(PreparedStatement ps) { // 遍历参数映射 for (ParameterMapping paramMapping : parameterMappings) { Object value; String propertyName = paramMapping.getProperty(); // 获取参数值(通过反射或TypeHandler) if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { // 使用MetaObject获取嵌套属性值 MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } // 获取TypeHandler设置参数 TypeHandler typeHandler = paramMapping.getTypeHandler(); typeHandler.setParameter(ps, i + 1, value, paramMapping.getJdbcType()); } } }
3. 结果集映射
- ResultSetHandler:处理结果映射
public class DefaultResultSetHandler implements ResultSetHandler { public List<Object> handleResultSets(Statement stmt) throws SQLException { // 1. 获取ResultMap ResultMap resultMap = mappedStatement.getResultMap(); // 2. 遍历结果集 while (rs.next()) { Object resultObject = createResultObject(rs, resultMap); // 3. 应用自动映射 applyAutomaticMappings(rs, resultObject); // 4. 应用显式映射 applyPropertyMappings(rs, resultObject); resultList.add(resultObject); } return resultList; } }
四、缓存机制实现原理
1. 一级缓存(Local Cache)
- 范围:SqlSession级别
- 实现类:
PerpetualCache
(使用HashMap) - 失效场景:
- 执行update操作(insert/update/delete)
- 手动调用
clearCache()
- 配置
flushCache=true
- 提交事务(commit)或回滚(rollback)
2. 二级缓存(Global Cache)
- 范围:Mapper(namespace)级别
- 启用条件:
<settings> <setting name="cacheEnabled" value="true"/> </settings> <mapper namespace="com.example.UserMapper"> <cache/> <!-- 启用二级缓存 --> </mapper>
- 实现原理:
3. 缓存执行顺序
五、动态SQL解析机制
1. 解析流程
public class XMLScriptBuilder {
protected SqlSource parseDynamicTags(XNode node) {
// 1. 解析SQL片段
List<SqlNode> contents = parseDynamicTags(node);
// 2. 创建MixedSqlNode
MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
// 3. 创建SqlSource
if (isDynamic) {
return new DynamicSqlSource(config, rootSqlNode);
} else {
return new RawSqlSource(config, rootSqlNode, parameterType);
}
}
}
2. SqlNode实现
SqlNode类型 | 对应标签 | 功能 |
---|---|---|
IfSqlNode | <if> | 条件判断 |
ForEachSqlNode | <foreach> | 循环遍历 |
TrimSqlNode | <trim> | 自定义字符串截取 |
WhereSqlNode | <where> | 自动处理WHERE条件 |
SetSqlNode | <set> | 自动处理SET更新语句 |
TextSqlNode | 文本 | 处理包含${}的动态文本 |
六、插件机制(Interceptor)
1. 拦截点(4大对象)
- Executor(update/query/commit/rollback)
- ParameterHandler(参数处理)
- ResultSetHandler(结果集处理)
- StatementHandler(SQL准备)
2. 实现原理(责任链模式)
3. 自定义插件示例
@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)
})
public class QueryInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long start = System.currentTimeMillis();
Object result = invocation.proceed(); // 执行原方法
long end = System.currentTimeMillis();
System.out.println("SQL执行耗时: " + (end - start) + "ms");
return result;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this); // 创建代理
}
}
七、Mapper接口绑定原理
1. 动态代理实现
public class MapperProxy<T> implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) {
// 1. 解析MapperMethod
MapperMethod mapperMethod = cachedMapperMethod(method);
// 2. 执行SQL命令
return mapperMethod.execute(sqlSession, args);
}
}
public class MapperMethod {
public Object execute(SqlSession sqlSession, Object[] args) {
switch (command.getType()) {
case SELECT:
return sqlSession.selectOne(command.getName(), param);
case INSERT:
return sqlSession.insert(command.getName(), param);
// ...
}
}
}
2. 方法签名解析
public class MapperMethod {
public static class MethodSignature {
public MethodSignature(Configuration config, Method method) {
// 解析返回类型
this.returnType = method.getReturnType();
// 解析参数
this.params = getParams(method);
// 解析@Param注解
this.paramNameResolver = new ParamNameResolver(config, method);
}
}
}
八、性能优化关键点
- Statement重用:使用
ReuseExecutor
- 批量操作:使用
BatchExecutor
- 分页优化:避免内存分页(使用物理分页)
- 结果集控制:
<!-- 关闭自动映射 --> <setting name="autoMappingBehavior" value="NONE"/>
- 延迟加载:
<setting name="lazyLoadingEnabled" value="true"/>
九、设计模式应用
设计模式 | 应用场景 | 实现类 |
---|---|---|
建造者模式 | 配置对象创建 | SqlSessionFactoryBuilder |
工厂模式 | SqlSession创建 | SqlSessionFactory |
代理模式 | Mapper接口实现 | MapperProxy |
装饰器模式 | 缓存实现 | CachingExecutor |
责任链模式 | 插件拦截器 | InterceptorChain |
模板方法模式 | 执行器操作流程 | BaseExecutor |
十、与JDBC对比优势
特性 | 原生JDBC | MyBatis |
---|---|---|
连接管理 | 手动创建/关闭 | 自动池化管理 |
SQL编写 | Java硬编码 | XML/注解分离管理 |
参数绑定 | 手动setParameter | 自动映射 |
结果映射 | 手动遍历ResultSet | 自动对象映射 |
缓存机制 | 无内置缓存 | 一级/二级缓存 |
事务控制 | 手动commit/rollback | 声明式事务管理 |
扩展性 | 低 | 插件机制扩展 |
总结:MyBatis 核心优势
- SQL控制灵活:原生SQL编写能力
- 映射智能化:自动参数绑定与结果映射
- 架构解耦:SQL与Java代码分离
- 缓存优化:多级缓存提升性能
- 扩展性强:插件机制支持深度定制
- 轻量级:无侵入式设计,依赖少
深入理解MyBatis底层原理的关键点:
- 动态代理:Mapper接口实现机制
- SQL解析:动态SQL生成过程
- 缓存体系:二级缓存实现原理
- 插件扩展:责任链拦截机制
- 执行流程:四大核心组件协作
通过分析源码(重点包:org.apache.ibatis.executor
、org.apache.ibatis.mapping
、org.apache.ibatis.scripting
)可进一步加深对MyBatis运行机制的理解。
MyBatis 是一款优秀的持久层框架,其核心目标是通过简化 JDBC 操作、实现 Java 对象与数据库表的映射(ORM),让开发者更高效地操作数据库。它的底层原理围绕核心组件协作、SQL 执行流程、ORM 映射机制和缓存优化展开。以下从底层架构、关键组件、执行流程到高级特性,全面解析 MyBatis 的底层原理。