MyBatis源码深度解析:架构设计与核心机制剖析
引言
MyBatis作为Java领域最受欢迎的持久层框架之一,自问世以来就以其灵活性和高性能著称。与传统的Hibernate等全自动ORM框架不同,MyBatis采用半自动化的数据映射方式,在保持SQL灵活性的同时,极大地简化了数据库操作。本文将深入MyBatis源码,从架构设计、核心组件、执行流程等多个维度进行全面解析,帮助开发者深入理解MyBatis的内部机制。
一、MyBatis整体架构设计
1.1 三层架构模型
MyBatis采用了经典的三层架构设计,分别是基础支撑层、核心处理层和接口层。
基础支撑层包含了整个框架的基础功能模块:
- 类型转换模块(Type Handler)
- 日志模块(Logging)
- 资源加载模块(Resources)
- 解析器模块(Parser)
- 数据源模块(DataSource)
- 事务管理模块(Transaction)
- 缓存模块(Cache)
- 绑定模块(Binding)
核心处理层是MyBatis框架的核心,主要包括:
- 配置解析(Configuration)
- SQL解析(SqlSource)
- SQL执行(Executor)
- 结果集映射(ResultSetHandler)
- 参数映射(ParameterHandler)
接口层提供了面向用户的高级API:
- SqlSession
- Mapper接口
- Mapper注解
1.2 核心组件协作关系
MyBatis的核心组件之间通过精密的协作完成整个数据库操作流程。SqlSession作为门面接口,接收用户请求并委托给Executor执行;Executor通过StatementHandler操作JDBC Statement对象;ParameterHandler负责参数映射;ResultSetHandler处理结果集映射。
二、配置解析机制深度解析
2.1 Configuration类的核心作用
Configuration类是MyBatis的核心配置容器,采用单例模式设计,在整个应用生命周期中只存在一个实例。它负责存储和管理所有的配置信息:
public class Configuration {
protected Environment environment;
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<>("Mapped Statements collection");
protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");
protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
}
2.2 XML配置解析过程
MyBatis通过XMLConfigBuilder解析主配置文件,这个过程涉及多个解析器的协作:
public class XMLConfigBuilder extends BaseBuilder {
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
private void parseConfiguration(XNode root) {
try {
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
}
2.3 映射文件解析细节
映射文件的解析由XMLMapperBuilder负责,重点在于SQL语句的解析和MappedStatement的构建:
public class XMLMapperBuilder extends BaseBuilder {
private void buildStatementFromContext(List<XNode> list) {
if (configuration.getDatabaseId() != null) {
buildStatementFromContext(list, configuration.getDatabaseId());
}
buildStatementFromContext(list, null);
}
private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
for (XNode context : list) {
final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
try {
statementParser.parseStatementNode();
} catch (IncompleteElementException e) {
configuration.addIncompleteStatement(statementParser);
}
}
}
}
三、SqlSession执行流程剖析
3.1 SqlSession的创建过程
SqlSession的创建通过SqlSessionFactory完成,DefaultSqlSession是默认实现:
public class DefaultSqlSession implements SqlSession {
private final Configuration configuration;
private final Executor executor;
private final boolean autoCommit;
private boolean dirty;
private List<Cursor<?>> cursorList;
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.dirty = false;
this.autoCommit = autoCommit;
}
}
3.2 SQL执行的核心链路
SQL执行的核心链路涉及多个组件的协作:
- SqlSession接收请求:用户调用selectOne、selectList等方法
- Executor执行查询:根据配置选择不同的Executor实现
- StatementHandler处理Statement:创建并配置PreparedStatement
- ParameterHandler设置参数:将Java参数转换为JDBC参数
- ResultSetHandler处理结果:将ResultSet转换为Java对象
public class DefaultSqlSession implements SqlSession {
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
}
四、Executor执行器机制详解
4.1 执行器类型与选择策略
MyBatis提供了三种执行器实现:
SimpleExecutor:最简单的执行器,每次执行都会创建新的Statement对象 ReuseExecutor:重用预处理语句的执行器 BatchExecutor:批处理执行器
执行器的选择通过配置决定:
public enum ExecutorType {
SIMPLE, REUSE, BATCH
}
4.2 二级缓存与执行器装饰
CachingExecutor是Executor的装饰器,为其他执行器添加二级缓存功能:
public class CachingExecutor implements Executor {
private final Executor delegate;
private final TransactionalCacheManager tcm = new TransactionalCacheManager();
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);
if (list == null) {
list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list);
}
return list;
}
}
return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
}
4.3 延迟加载机制
MyBatis通过Javassist或CGLIB实现延迟加载,主要涉及ProxyFactory和LazyLoader:
public class JavassistProxyFactory implements ProxyFactory {
@Override
public Object createProxy(Object target, ResultLoaderMap lazyLoader, Configuration configuration, ObjectFactory objectFactory, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
return EnhancedResultObjectProxyImpl.createProxy(target, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
}
private static class EnhancedResultObjectProxyImpl implements MethodHandler {
@Override
public Object invoke(Object enhanced, Method method, Method methodProxy, Object[] args) throws Throwable {
final String methodName = method.getName();
try {
synchronized (lazyLoader) {
if (WRITE_REPLACE_METHOD.equals(methodName)) {
Object original = null;
if (constructorArgTypes.isEmpty()) {
original = objectFactory.create(type);
} else {
original = objectFactory.create(type, constructorArgTypes, constructorArgs);
}
PropertyCopier.copyBeanProperties(type, enhanced, original);
return original;
} else {
if (lazyLoader.size() > 0 && !FINALIZE_METHOD.equals(methodName)) {
lazyLoader.loadAll();
}
}
}
return methodProxy.invoke(enhanced,

评论框