本文导读
本文解析 MyBatis 工作流程源码, 【总】 可以把 MyBatis 的运行流程分为三大阶段: 1. 初始化阶段 ; 2. 代理封装阶段 ; 3. 数据访问阶段 ;
一、MyBatis 工作原理(运行流程)
【总】可以把 MyBatis 的运行流程分为三大阶段:
1. 初始化阶段:读取 XML 配置文件和注解中的配置信息,创建配置对象,并完成各个模块的初始化的工作;
2. 代理封装阶段:封装 iBatis 的编程模型,使用 mapper 接口开发的初始化工作;
3. 数据访问阶段:通过 SqlSession 完成 SQL 的解析,参数的映射、SQL 的执行、结果的解析过程;
1、MyBatis 工作流程简述
(1)读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
(2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
(3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
(4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
(5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
(6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
(7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
(8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
二、MyBatis 工作流程源码分析
这部分我们要知道 MyBatis 初始化流程源码,MyBatis 是如何加载配置文件的? Mapper.xml 映射文件是如何解析的? SQL 语句是如何解析 ( <select>
、 <insert>
、 <delete>
、 <update>
等 SQL 语句标签) ?
在初始化的过程中,MyBatis 会读取 mybatis-config.xml 这个全局配置文件以及所有的 Mapper 映射.xml 配置文件,同时还会加载这两个配置文件中指定的类,解析类中的相关注解,最终将解析得到的信息转换成配置对象。 完成配置加载之后,MyBatis 就会根据得到的配置对象初始化各个模块 。
1、mybatis-config.xml 解析全流程
下面我们正式开始介绍 MyBatis 的初始化过程(工作过程、工作原理)。
MyBatis 初始化的第一个步骤就是加载和解析 mybatis-config.xml 这个全局配置文件,入口是 XMLConfigBuilder 这个 Builder 对象,它由 SqlSessionFactoryBuilder.build() 方法创建。XMLConfigBuilder 会解析 mybatis-config.xml 配置文件得到对应的 Configuration 全局配置对象,然后 SqlSessionFactoryBuilder 会根据得到的 Configuration 全局配置对象创建一个 DefaultSqlSessionFactory 对象返回给上层使用。
在 SqlSessionFactoryBuilder.build() 方法中也可以看到,XMLConfigBuilder.parse() 方法触发了 mybatis-config.xml 配置文件的解析, 其中的 parseConfiguration() 方法定义了解析 mybatis-config.xml 配置文件的完整流程 ,核心步骤如下:
解析 <properties> 标签;
解析 <settings> 标签;
处理日志相关组件;
解析 <typeAliases> 标签;
解析 <plugins> 标签;
解析 <objectFactory> 标签;
解析 <objectWrapperFactory> 标签;
解析 <reflectorFactory> 标签;
解析 <environments> 标签;
解析 <databaseIdProvider> 标签;
解析 <typeHandlers> 标签;
解析 <mappers> 标签。
public abstract class BaseBuilder {
protected final Configuration configuration;
protected final TypeAliasRegistry typeAliasRegistry;
protected final TypeHandlerRegistry typeHandlerRegistry;
protected Class<?> resolveAlias(String alias) {
return typeAliasRegistry.resolveAlias(alias);
}
protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, String typeHandlerAlias) {
if (typeHandlerAlias == null) {
return null;
}
Class<?> type = resolveClass(typeHandlerAlias);
if (type != null && !TypeHandler.class.isAssignableFrom(type)) {
throw new BuilderException("Type " + type.getName() + " is not a valid TypeHandler because it does not implement TypeHandler interface");
}
@SuppressWarnings( "unchecked" ) // already verified it is a TypeHandler
Class<? extends TypeHandler<?>> typeHandlerType = (Class<? extends TypeHandler<?>>) type;
return resolveTypeHandler(javaType, typeHandlerType);
}
protected TypeHandler<?> resolveTypeHandler(Class<?> ja