# MyBatis-Spring 的整合
mybatis 和 spring 的整合需要先注入 SqlSessionFactoryBean 和 MapperScannerConfigurer, 那么这两个类的作用是什么呢?
# MyBatis 的执行流程
1 | void test() { |
- 通过 SqlSessionFactoryBuilder 将读取到的 mybatis-config.xml 配置文件生成 SqlSessionFactory
- 通过 SqlSessionFactory 生成 SqlSession 对象
- 通过 SqlSession 的方法进行数据库请求 / 通过 SqlSession 获取动态代理 Mapper 对象
- 通过 Mapper 进行数据库操作
SqlSessionFactoryBuilder :
用于创建 SQLSessionFactory 对象的类,我推测应该就是建造者模式,创建完之后就没有用处了,所以应该为局部方法变量
SqlSessionFactory :
一个应用程序中最好只有一个,即单例
SqlSession :
线程不安全,所以不能被共享,每个线程都应该有它自己的 SqlSession 实例
# MyBatis-Spring : 将 MyBatis 代码无缝整合到 Spring
MyBaits-Spring 会将 MyBatis 代码无缝的整合到 Spring 中,他将允许 MyBats 参与到 Spring 的事务管理中,创建映射器 mapper 和 SqlSession 并注入到 Bean 中
在 Spring 项目中应用了 MyBatis 都会有下面的两个 Bean 配置,这两个配置就是实现 xml 加载,mapper 和 SqlSession 注入的起始配置
1 |
|
# SqlSessionFactoryBean : 加载 xml 及 build SqlSessionFactory 对象
我们可以从上面的配置看出,SqlSessionFactoryBean 配置了数据源,mapper 的 xml 路径以及 configuration 的 xml 路径,所以其内部一定实现了解析 xml 配置文件和 SqlSessionFactory 对象的创建. SqlSessionFactoryBean 继承关系图如下 :

FactoryBean 子类都是通过 getObject () 方法来获取到实际的 Bean 对象的,在 SqlSessionFactoryBean 中也就是获取 SqlSessionFactory, 而创建 SqlSessionFactory 势必需要一个 Configuration 类 (MyBatis 的核心类之一,主要用来存放读取到的 xml 配置,包括 mapper.xml)
关键类及方法 :
- XMLConfigBuilder : 通过调用其 parse () 方法来解析 mybatis-config.xml 配置,如果有 mapper.xml, 其会通过 XMLMapperBuilder 进行解析加载,并将解析的数据赋值到 Configuration
- XMLMapperBuilder : 通过调用其 parse () 方法来解析 mapper.xml 配置,并将解析的数据赋值到 Configuration
- 将放油解析数据的 Configuration 作为 SqlSessionFactoryBuilder.builder () 的参数,创建 SqlSessionFactory 对象
# MapperScannerConfigurer : 扫描 Mapper 接口路径,将 Mapper 偷梁换柱成 MaooerFactoryBean
MapperScannerConfigurer 是 MyBatis-Spring 项目中为了实现方便加载 Mapper 接口,以及将 Mapper 偷梁换柱成 MaooerFactoryBean (在 Spring 中是无法直接将接口注册成 Bean 的,接口无法实例化,而 Spring 在创建 Bean 的过程中会调用构造函数)
查看继承关系图 :

整个方法分为三部分 :
- 调用父类 ClassPathBeanDefinitionScanner 的 doScan () 方法加载路径下所有 mapper 生成对应的 BeanDefinition
- 通过 definnition.setBeanClass (MapperFactoryBean.class) 偷梁换柱成 MapperFactoryBean
- 通过 definition.getPropertyValues ().add () 添加 MapperFacotryBean 所需的字段或者方法参数信息 : sqlSessionFactory, mapperInterface 等
# 加载 Configuration
Configuration 包含了会深深影响 MyBatis 行为的设置和属性信息。配置文档的顶层结构如下
- configuration
- properties (属性)
- settings (设置)
- typeAliases (类型别名)
- typeHandlers (类型处理器)
- objectFactory (对象工厂)
- plugins (插件)
- environments (环境配置)
- environment (环境变量)
- transactionManager (事务管理器)
- dataSource (数据源)
- databaseIdProvider (数据库厂商标识)
- mapper (映射器)
其中我们最常配置的是 settings. 一个配置相对完整的 settings 元素的示例如下 :
1 |
|

# Mapper 代理类的生成
# 加载 Mapper 接口
加载 mapper 接口有两种形式:一种是根据设置的 package 找到路径下面所有的 class 并通过 configuration.addMapper () 加载。另一种是根据设置的 Mapper 接口路径直接通过 configuration.addMapper () 加载 class. 所以加载 Mapper 接口最终都是 configuration.addMapper () 来实现的
而针对 MyBatis-Spring 项目,则是获取 MapperScannerConfigurer 的 basePackage 参数,并通过 ClassPathMapperScanner 扫描到设置的 basePackage 路径下的所有 class, 并得到 BeanDefinition, , 最终是得到了 MapperFactoryBean
- Configuration 维护了一个 MapperRegistry 对象,该对象的主要作用就是加载 Mapper 接口和获取 MapperProxy
- MapperRegistry 维护了一个 key 为 mapper 接口 class 对象,value 为 MapperProxyFactory 的 map
- MapperProxy 是通过 MapperProxyFactory 创建的
- MapperProxy 实现 Mapper 接口方法是委托 MapperMethod 执行的
- MapperMethod 执行接口方法时通过 SqlCommand 来判断要执行的具体 SQL 节点,并最终委托 SqlSession 执行
- SqlCommand 内部的信息是通过 MapperStatement 中获取的
