Mybatis 与 Springboot 集成过程详解
- [一. 核心概念与优势](#一. 核心概念与优势)
- [二.Mybatis 核心类简介](#二.Mybatis 核心类简介)
-
- 1.MybatisAutoConfiguration
- 2.MapperScans
- 3.MapperScannerRegistrar
- 4.MapperFactoryBean
- 5.Configuration
- 6.MapperRegistry
- [7.MapperProxy 与 MapperProxyFactory](#7.MapperProxy 与 MapperProxyFactory)
-
- 7.1核心定位与职责
- [7.22. MapperProxy(动态代理处理器)](#7.22. MapperProxy(动态代理处理器))
- [7.3 协作流程与执行机制](#7.3 协作流程与执行机制)
- 三.参考图
一. 核心概念与优势
在开始之前,先快速了解为什么这种集成如此流行:
-
MyBatis: 一个优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。它避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
-
Spring Boot: 旨在简化 Spring 应用的初始搭建和开发过程,提供了大量的自动配置。
-
集成优势:
-
简化配置: Spring Boot 为 MyBatis 提供了官方 starter,极大减少了 XML 配置。
-
自动装配: 自动配置 SqlSessionFactory、SqlSessionTemplate、DataSource等 bean。
-
无缝整合: 与 Spring 的事务管理、AOP 等特性完美结合
-
二.Mybatis 核心类简介
1.MybatisAutoConfiguration
MybatisAutoConfiguration 是 MyBatis Spring Boot Starter 的核心自动配置类,通过 META-INF/spring.factories文件注册到 Spring 容器中。当应用启动时,@EnableAutoConfiguration会触发其加载,前提是满足以下条件:
-
类路径存在 SqlSessionFactory和 SqlSessionFactoryBean(确保 MyBatis 核心依赖已引入)。
-
容器中存在唯一的数据源 Bean(依赖 DataSourceAutoConfiguration完成数据源配置)。
-
在数据源配置完成后执行(通过 @AutoConfigureAfter(DataSourceAutoConfiguration.class)控制加载顺序)
2.MapperScans
基本功能与作用
.
1.批量扫描注册
-
自动扫描指定包路径下的 Mapper 接口,生成 BeanDefinition并注册到 Spring 容器。
-
避免在每个 Mapper 接口上单独添加 @Mapper注解,简化配置。
2.支持多路径与通配符
-
支持数组形式指定多个包路径(如 @MapperScan({"com.dao.user", "com.dao.product"}))。
-
支持通配符匹配(如 com.example.*.mapper扫描一级子包,com.example.**.mapper扫描多级子包)。
3.多数据源适配
- 结合 sqlSessionFactoryRef或 sqlSessionTemplateRef属性,为不同数据源指定独立的 SQL 会话工厂或模板
核心属性解析
属性名 | 功能说明 | 示例 |
---|---|---|
value/ basePackages | 指定扫描的包路径(支持数组) | @MapperScan("com.dao") |
basePackageClasses | 通过类的包路径定位扫描范围(类型安全) | @MapperScan(basePackageClasses=UserMapper.class) |
annotationClass | 仅扫描带有指定注解的接口(默认扫描所有接口) | annotationClass = Repository.class |
markerInterface | 仅扫描继承指定父接口的接口 | markerInterface = BaseMapper.class |
sqlSessionFactoryRef | 指定多数据源下使用的 SqlSessionFactoryBean 名称 | sqlSessionFactoryRef = "ds1SqlSessionFactory" |
factoryBean | 自定义 MapperFactoryBean实现类(需继承 MapperFactoryBean) | factoryBean = CustomMapperFactoryBean.class |
3.MapperScannerRegistrar
核心定位与作用
1.注解解析枢纽
@MapperScan注解通过 @Import(MapperScannerRegistrar.class)引入该类,使其成为 Spring 容器启动时处理 Mapper 扫描配置的入口点。
2.动态注册引擎
实现 ImportBeanDefinitionRegistrar接口,在 Spring 容器初始化阶段动态注册 MapperScannerConfigurer的 BeanDefinition,从而将用户配置(如包路径、过滤条件)转化为 Spring 可执行的扫描任务。
3.多数据源适配桥梁
支持通过 sqlSessionFactoryRef或 sqlSessionTemplateRef属性关联特定数据源,解决多数据源场景下 Mapper 与 SQL 会话工厂的绑定问题
核心实现机制
- 注解属性解析
- 读取 @MapperScan中的 basePackages、basePackageClasses等属性,构建待扫描的包路径列表。
- 解析过滤条件(如 annotationClass、markerInterface),定制扫描范围。
- ClassPathMapperScanner 初始化
创建 ClassPathMapperScanner对象(继承自 Spring 的 ClassPathBeanDefinitionScanner),并配置其属性:
- 设置资源加载器(ResourceLoader)
- 注入自定义的 Bean 名称生成器(BeanNameGenerator)
- 定 Mapper 代理工厂类(MapperFactoryBean)。
- 接口扫描与代理转换
调用 scanner.doScan()方法扫描目标包路径,通过重写 isCandidateComponent()确保仅扫描接口类型:扫描完成后,将接口的 BeanDefinition 替换为 MapperFactoryBean类型,并注入构造参数(原接口类名),为后续动态代理奠基
- ClassPathMapperScanner
- 应用启动时,实际注入到服务层的Mapper接口,就是这个转换后的代理类实例
4.MapperFactoryBean
MapperFactoryBean→ SqlSessionDaoSupport→ DaoSupport
MapperFactoryBean 是 MyBatis-Spring 整合的核心组件,负责将 MyBatis 的 Mapper 接口动态代理并注册为 Spring 容器中的 Bean,从而简化数据访问层的开发。其设计基于 Spring 的 FactoryBean接口,实现了接口代理与资源管理的自动化
1.动态代理生成
MapperFactoryBean 通过 JDK 动态代理技术,为 Mapper 接口创建代理对象。当调用接口方法时,代理对象将请求转发给 MyBatis 的 SqlSession,执行对应的 SQL 操作。无需手动编写实现类,显著减少冗余代码
2.资源生命周期管理
自动管理 SqlSession的开启、关闭及事务控制:
- 会话绑定:确保每次操作在正确的 SqlSession中执行。
- 事务集成:与 Spring 事务管理器协同,支持声明式事务(如 @Transactional)。
3.异常转换
将 MyBatis 的 PersistenceException转换为 Spring 的 DataAccessException体系,统一异常处理
MapperFactoryBean 是 MyBatis-Spring 整合的动态代理枢纽,通过三大核心能力简化开发:
- 自动化代理生成:消除 DAO 实现类,直接操作接口。
- 资源管理集成:无缝管理 SqlSession生命周期与 Spring 事务。
- 灵活配置扩展:支持 XML 显式声明或注解批量扫描,适配单数据源与多数据源场景
5.Configuration
全类名:org.apache.ibatis.session.Configuration
1.全局配置容器
Configuration对象在 MyBatis 初始化时创建(通常通过解析 mybatis-config.xml或 Java API 构建),集中存储以下配置:
- 环境信息():包含数据源(DataSource)和事务管理器(TransactionFactory),支撑数据库连接与事务控制。
- 全局设置():如 cacheEnabled(二级缓存开关)、lazyLoadingEnabled(延迟加载)、mapUnderscoreToCamelCase(下划线转驼峰)等运行时行为开关。
- 注册中心:管理类型别名(TypeAliasRegistry)、类型处理器(TypeHandlerRegistry)、插件(InterceptorChain)等扩展点。
2.SQL 语句管理中心
维护关键映射组件的注册表,以 Map结构存储:
- mappedStatements:管理所有 SQL 操作(Select/Insert/Update/Delete),Key 为 SQL 语句 ID(如 "com.example.UserMapper.selectById")。
- resultMaps:存储结果集映射规则()。
- caches:管理命名空间级别的二级缓存。
3.核心组件工厂
提供方法创建 MyBatis 执行链的关键对象:
- newExecutor():生成 Executor(SQL 执行器),支持 SIMPLE、REUSE、BATCH三种模式。
- newStatementHandler():创建 StatementHandler(处理 JDBC Statement)。
- newParameterHandler()/ newResultSetHandler():处理参数绑定与结果集映射
Configuration作为 MyBatis 的配置中枢与运行时引擎,通过三大核心能力支撑框架运作:
1.统一配置管理:整合 XML/注解/Javaconfig 配置源,提供全局访问接口。
2.组件调度工厂:动态创建 Executor、StatementHandler等核心执行链对象。
3.扩展性基石:通过拦截器链(InterceptorChain)和类型处理器(TypeHandlerRegistry)支持深度定制
6.MapperRegistry
MapperRegistry是 MyBatis 框架中管理 Mapper 接口注册与代理对象生成的核心组件,作为 MyBatis 配置中枢 Configuration的一部分,它在框架启动时初始化,并在运行时支撑面向接口的数据库操作模式。
核心作用与定位
1.Mapper 接口的注册中心
MapperRegistry集中管理所有需被 MyBatis 识别的 Mapper 接口,确保接口与 SQL 映射的关联。它通过内部维护的映射表 knownMappers(类型为 Map<Class<?>, MapperProxyFactory<?>>)实现:
Key:Mapper 接口的 Class对象(如 UserMapper.class)。
Value:为该接口创建的代理工厂 MapperProxyFactory,用于生成动态代理对象。
2.动态代理对象的提供者
当调用 sqlSession.getMapper(UserMapper.class)时,SqlSession委托 MapperRegistry查找接口对应的 MapperProxyFactory,并生成代理对象。此代理对象拦截接口方法调用,将其转化为 SQL 执行逻辑。
3.接口与 SQL 映射的绑定枢纽
在注册阶段,MapperRegistry触发注解或 XML 的解析(通过 MapperAnnotationBuilder),将接口方法关联到具体的 SQL 语句(MappedStatement),实现方法调用 → SQL 执行的动态绑定
MapperRegistry是 MyBatis 面向接口编程的基石,通过三层次协作实现高效数据访问:
1.注册层:统一管理 Mapper 接口,关联代理工厂。
2.代理层:动态生成代理对象,拦截方法调用。
3.执行层:将方法调用路由至 SqlSession,执行具体 SQL
7.MapperProxy 与 MapperProxyFactory
MapperProxy 与 MapperProxyFactory 是 MyBatis 实现 Mapper 接口动态代理的核心组件,二者协同完成接口方法与 SQL 语句的绑定,使开发者无需编写实现类即可操作数据库
7.1核心定位与职责
- MapperProxyFactory(代理对象工厂)
- 职责:
负责生产 Mapper 接口的代理对象实例(MapperProxy)。每个 Mapper 接口对应一个独立的 MapperProxyFactory实例。 - 关键属性:
- mapperInterface:需代理的 Mapper 接口 Class 对象(如 UserMapper.class)
- methodCache:缓存接口方法与 MapperMethod的映射,避免重复解析
7.22. MapperProxy(动态代理处理器)
- 职责:
实现 InvocationHandler接口,拦截 Mapper 接口方法调用,将其转换为底层 SQL 执行逻辑。 - 关键依赖:
- SqlSession:执行 SQL 的会话对象。
- methodCache:缓存方法对应的 MapperMethod,优化性能。
- 代理控制逻辑:
- Object 原生方法(如 toString):直接调用原生实现。
- 接口默认方法:调用默认方法实现。
- 抽象方法:委托给 MapperMethod执行 SQL
7.3 协作流程与执行机制
代理对象生成流程
1.注册阶段:
MyBatis 启动时通过 MapperRegistry扫描并注册所有 Mapper 接口,为每个接口创建 MapperProxyFactory实例。
2.调用阶段:
用户调用 sqlSession.getMapper(UserMapper.class):
- MapperRegistry查找接口对应的 MapperProxyFactory。
- MapperProxyFactory生成代理对象(内部创建 MapperProxy并绑定至接口)。
- 方法拦截与 SQL 执行
当调用代理对象的接口方法(如 userMapper.selectById(1)):
1.方法拦截:
MapperProxy.invoke()拦截调用,跳过非抽象方法(如 Object方法)。
2.方法映射:
通过 cachedMapperMethod()获取或创建 MapperMethod对象(封装 SQL 语句、参数映射、返回类型)。
3.SQL 执行:
MapperMethod.execute()根据操作类型(SELECT/UPDATE)调用 SqlSession的对应方法(如 selectOne()),并返回结果
总结
- MapperProxyFactory 是代理对象的生产引擎,通过工厂模式屏蔽动态代理的复杂性。
- MapperProxy 是代理逻辑的执行枢纽,将接口方法调用转化为 SQL 会话操作,实现 ORM 的"接口即实现"范式
- 协同价值:二者通过动态代理机制,彻底解耦接口定义与 SQL 执行,成为 MyBatis 简化 DAO 层开发的核心设计,也是其区别于传统 ORM 框架的标志性特性
三.参考图
