MyBatis 核心架构与启动流程剖析:从配置到初始化
- [一、MyBatis 核心架构设计](#一、MyBatis 核心架构设计)
- [二、MyBatis 启动流程全解析](#二、MyBatis 启动流程全解析)
-
- [2.1 配置加载阶段:从 XML 到 Configuration 对象](#2.1 配置加载阶段:从 XML 到 Configuration 对象)
- [2.2 核心类初始化:Configuration 的构建](#2.2 核心类初始化:Configuration 的构建)
- [2.3 会话工厂构建:SqlSessionFactory 的创建](#2.3 会话工厂构建:SqlSessionFactory 的创建)
- 三、关键流程图
-
- [3.1 MyBatis 启动核心流程](#3.1 MyBatis 启动核心流程)
- [3.2 MyBatis 映射器解析流程](#3.2 MyBatis 映射器解析流程)
- [3.3 MyBatis 执行器初始化流程](#3.3 MyBatis 执行器初始化流程)
- 四、核心类介绍
- 五、总结
Mybatis的demo项目

user表的DDL 语句:
sql
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`name` varchar(50) DEFAULT NULL COMMENT '用户姓名',
`age` int DEFAULT NULL COMMENT '用户年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户信息表';
User类:
java
@Data
public class User {
private int id;
private String name;
private int age;
}
UserMapper类:
java
public interface UserMapper {
User getUserById(int id);
}
UserMapper.xml:
xml
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.coderzpw.dao.UserMapper">
<select id="getUserById" resultType="com.coderzpw.domain.User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>
Mybatis主配置:
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<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/mybatis_study" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 设置mapping文件路径配置 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
测试类:
java
public class MybatisTest {
private SqlSessionFactory sessionFactory;
/**
* 加载配置文件。并且初始化SqlSessionFactory
*/
@Before
public void before() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testGetById() {
SqlSession sqlSession = sessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
System.out.println(user);
}
}
一、MyBatis 核心架构设计
MyBatis 作为一款优秀的持久层框架,其架构设计遵循 "约定优于配置" 的原则,通过分层设计实现了数据库操作的解耦。核心架构主要分为以下几层:
1. 配置层(Configuration Layer)
- 作用 :负责加载 MyBatis 配置文件(
mybatis-config.xml
)及映射文件(.xml
或注解),构建框架运行时所需的元数据 - 核心类 :
Configuration
(存储全局配置信息,如数据源、插件、映射器等)
2. 会话层(Session Layer)
- 作用:提供数据库操作的会话接口,封装 SQL 的执行逻辑
- 核心类 :
SqlSessionFactory
(会话工厂,用于创建SqlSession
)SqlSession
(会话接口,包含增删改查等方法)
3. 执行层(Executor Layer)
- 作用:负责 SQL 的解析、参数映射、结果集转换等具体执行逻辑。
- 核心类 :
Executor
(执行器,处理 SQL 执行流程,支持简单、复用、批量执行模式)StatementHandler
(语句处理器,封装 PreparedStatement 的操作)
4. 数据层(Data Layer)
- 作用:与数据库建立连接,执行物理 IO 操作。
- 核心类 :
DataSource
(数据源,管理数据库连接)、Transaction
(事务管理)。
二、MyBatis 启动流程全解析
MyBatis
的启动流程可分为 配置加载 、核心类初始化 、会话工厂构建 三个阶段,下面结合源码详细分析

java
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
java
// 核心方法:通过 XML 构建 SqlSessionFactory
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
// 解析 XML 配置文件,生成 Configuration 对象
final XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
final Configuration config = parser.parse(); // 关键方法
// 构建 SqlSessionFactory(默认使用 DefaultSqlSessionFactory)
return new DefaultSqlSessionFactory(config);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// 异常处理
}
}
}
2.1 配置加载阶段:从 XML 到 Configuration 对象
XMLConfigBuilder.parse () 解析逻辑
java
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
java
private void parseConfiguration(XNode root) {
try {
// 解析 properties 节点(外部属性)
propertiesElement(root.evalNode("properties"));
// 解析 settings 节点(全局配置项,如延迟加载、缓存等
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
// 解析 typeAliases 类型别名
typeAliasesElement(root.evalNode("typeAliases"));
// 解析 plugins 插件
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// 解析 environments 节点(包含数据源配置)
environmentsElement(root.evalNode("environments"));
// 解析 databaseIdProvider 数据库厂商识别
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
// 【重点】:解析 mappers 节点(SQL 映射文件)
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
关键步骤:加载映射器(mappersElement)
java
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) { // 按包扫描映射器
String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage); // 注册包下所有接口
} else { // 按单个文件或类路径加载
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
if (resource != null && url == null && mapperClass == null) {
// 从类路径加载 XML 映射文件
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse(); // 解析 XML 中的 SQL 语句
} else if (resource == null && url != null && mapperClass == null) {
// 从 URL 加载映射文件
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null && mapperClass != null) {
// 注册接口(通过注解配置 SQL)
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
2.2 核心类初始化:Configuration 的构建
其实代码走完parseConfiguration()
,configuration
对象就已经初始化完成了
Configuration
是 MyBatis 的 "大脑",存储了框架运行所需的所有元数据,其关键属性包括:
java
public class Configuration {
// 数据源与事务
protected Environment environment; // 环境配置(数据源、事务工厂)
// 映射器与 SQL 缓存
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection"); // 存储解析后的 SQL 语句
protected final Map<String, SqlSource> sqlFragments = new StrictMap<SqlSource>("XML fragments"); // 存储 <sql> 片段
// 类型处理器与对象工厂
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(this); // 类型转换注册器
protected final ObjectFactory objectFactory = new DefaultObjectFactory(); // 对象工厂
protected final ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory(); // 对象包装工厂
// 插件链
protected final InterceptorChain interceptorChain = new InterceptorChain(); // 插件链
// ...
}
初始化流程关键点:
- 类型别名注册 :将
java.lang.Integer
等类型映射为int
等简称,简化配置 - 插件注册 :通过
interceptorChain.addInterceptor(plugin)
将插件织入目标对象(如Executor
、StatementHandler
等) - 映射器注册 :将接口和
XML
中的SQL
语句关联,生成MappedStatement
对象(包含SQL
语句、参数类型、结果集映射等信息)
2.3 会话工厂构建:SqlSessionFactory 的创建

核心类:DefaultSqlSessionFactory
java
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration; // 持有 Configuration 对象
// 构造函数
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
// 创建会话时指定执行器类型(默认 SIMPLE)
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction transaction = null;
try {
// 1. 获取环境配置中的事务工厂
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
// 2. 创建事务对象(连接管理)
transaction = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
// 3. 创建执行器(Executor)
final Executor executor = configuration.newExecutor(transaction, execType);
// 4. 创建 SqlSession(默认使用 DefaultSqlSession)
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
closeTransaction(transaction); // 异常时关闭事务
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
}
执行器(Executor
)初始化逻辑
java
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction); // 批量执行器
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction); // 可重用执行器(缓存 Statement)
} else {
executor = new SimpleExecutor(this, transaction); // 简单执行器(每次创建新 Statement)
}
// 插件拦截器链:为执行器添加插件功能
if (cacheEnabled) {
executor = new CachingExecutor(executor); // 装饰器模式,添加缓存功能
}
// 应用插件(重点!通过 InterceptorChain 对目标对象进行包装)
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
三、关键流程图
3.1 MyBatis 启动核心流程
java
┌─────────────────────────────────────────────────────────────────────┐
│ 配置加载阶段 │
│ │
│ SqlSessionFactoryBuilder.build() │
│ └── XMLConfigBuilder.parse() │
│ ├── propertiesElement() 解析外部属性 │
│ ├── settingsElement() 解析全局配置 │
│ ├── typeAliasesElement() 解析类型别名 │
│ ├── pluginElement() 解析插件配置 │
│ ├── environmentsElement() 解析数据源与事务配置 │
│ ├── databaseIdProviderElement() 解析数据库厂商识别 │
│ └── mappersElement() 解析映射器文件 │
│ │
└─────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────┐
│ 核心类初始化阶段 │
│ │
│ Configuration 对象构建 │
│ ├── 注册类型别名(简化配置书写) │
│ ├── 注册插件(InterceptorChain 管理) │
│ ├── 注册映射器(生成 MappedStatement 集合) │
│ ├── 管理数据源与事务配置(Environment、DataSource) │
│ └── 维护类型处理器与对象工厂(TypeHandlerRegistry、ObjectFactory)│
│ │
└─────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────┐
│ 会话工厂构建阶段 │
│ │
│ DefaultSqlSessionFactory 创建 │
│ ├── 持有 Configuration 对象 │
│ ├── openSession() 方法创建 SqlSession │
│ │ ├── 获取 Environment 配置 │
│ │ ├── 创建事务对象(TransactionFactory.newTransaction()) │
│ │ ├── 创建执行器(Configuration.newExecutor()) │
│ │ │ ├── 根据类型创建 Simple/Reuse/Batch Executor │
│ │ │ ├── 启用缓存时包裹 CachingExecutor │
│ │ │ └── 应用插件链(InterceptorChain.pluginAll()) │
│ │ └── 创建 DefaultSqlSession(持有 config 和 executor) │
│ └── 提供会话创建入口,是应用与 MyBatis 交互起点 │
│ │
└─────────────────────────────────────────────────────────────────────┘
3.2 MyBatis 映射器解析流程
java
┌─────────────────────────────────────────────────────────────────────┐
│ 映射器解析阶段 │
│ │
│ mappersElement 方法解析 │
│ ├── 按包扫描(<package> 标签) │
│ │ └── 注册包下所有接口(Configuration.addMappers()) │
│ ├── 加载单个映射文件(<resource>/<url>/<class> 标签) │
│ │ ├── <resource> 从类路径加载 XML 映射文件 │
│ │ │ ├── 创建 XMLMapperBuilder 解析器 │
│ │ │ ├── 解析 XML 中的 SQL 语句(生成 MappedStatement) │
│ │ │ └── 注册到 Configuration 的 mappedStatements 集合 │
│ │ ├── <url> 从 URL 加载映射文件 │
│ │ └── <class> 注册接口(通过注解配置 SQL) │
│ └── 建立接口与 XML 中 SQL 语句的关联关系 │
│ │
└─────────────────────────────────────────────────────────────────────┘
3.3 MyBatis 执行器初始化流程
java
┌─────────────────────────────────────────────────────────────────────┐
│ 执行器初始化阶段 │
│ │
│ Configuration.newExecutor() 方法 │
│ ├── 根据 ExecutorType 创建基础执行器 │
│ │ ├── ExecutorType.BATCH -> BatchExecutor │
│ │ ├── ExecutorType.REUSE -> ReuseExecutor │
│ │ └── 默认 ExecutorType.SIMPLE -> SimpleExecutor │
│ ├── 检查是否启用缓存(cacheEnabled) │
│ │ └── 是则使用 CachingExecutor 装饰器包装 │
│ ├── 应用插件链(InterceptorChain.pluginAll()) │
│ │ ├── 遍历插件集合(interceptors) │
│ │ ├── 对每个插件调用 plugin(target) 方法进行包装 │
│ │ └── 返回增强后的执行器对象 │
│ └── 生成具备 SQL 执行、缓存处理、插件增强能力的执行器 │
│ │
└─────────────────────────────────────────────────────────────────────┘
四、核心类介绍
核心类 | 作用描述 |
---|---|
Configuration | 存储全局配置信息,是 MyBatis 的 "配置中心",贯穿整个启动流程 |
SqlSessionFactory | 工厂类,负责创建 SqlSession,是应用与 MyBatis 交互的入口 |
Executor | 执行 SQL 的核心组件,处理参数映射、结果集转换,支持不同执行策略(简单 / 批量 / 复用) |
MappedStatement | 单条 SQL 的封装对象,包含 SQL 语句、参数类型、结果映射等元数据 |
五、总结
MyBatis 的启动流程是一个典型的 "配置驱动 " 过程,通过解析 XML
配置文件构建运行时所需的元数据,然后基于这些元数据创建核心组件。整个过程可以概括为:
- 配置解析阶段 :从
XML
配置文件中读取配置信息,构建Configuration
对象 - 核心类初始化阶段 :初始化
Configuration
中的各种组件,如数据源、映射器、插件等 - 会话工厂构建阶段 :创建
SqlSessionFactory
,用于后续创建SqlSession
- 执行器初始化阶段 :创建不同类型的执行器,处理
SQL
执行逻辑
理解 MyBatis
的启动流程有助于我们更好地使用和优化 MyBatis
,例如通过自定义插件扩展功能,通过合理配置提高性能,以及在遇到问题时能够快速定位和解决