mybatis-spring-boot-autoconfigure"] B --> C["MybatisAutoConfiguration 自动配置类"] %% 数据源依赖 D["Spring 数据源自动配置
(HikariCP/Druid等)"] --> C %% MybatisAutoConfiguration 构建核心组件 C --> E["SqlSessionFactory
(存储全局配置/创建SqlSession)"] C --> F["SqlSessionTemplate
(线程安全的Sql执行器)"] E --> F["SqlSessionTemplate"] %% 事务整合 G["SpringManagedTransactionFactory"] --> E["SqlSessionFactory"] H["Spring 事务管理器
(@Transactional)"] --> G %% Mapper扫描与代理 I["@MapperScan 注解"] --> J["MapperScannerRegistrar"] J --> K["MapperScannerConfigurer
(扫描Mapper接口)"] K --> L["Mapper接口
(com.test.core.mapper)"] F --> M["Mapper代理对象
(MyBatis动态代理)"] L --> M %% 配置文件关联 N["application.yml
(mybatis前缀配置)"] --> C O["mybatis-config.xml
(全局配置)"] --> E P["Mapper XML映射文件
(mapper/**/*.xml)"] --> E %% 业务层调用 M --> Q["Service层
(@Autowired注入Mapper)"] %% 样式优化 classDef config fill:#f0f8ff,stroke:#4169e1,stroke-width:2px classDef core fill:#fdf2f8,stroke:#9c27b0,stroke-width:2px classDef scan fill:#e8f4f8,stroke:#00bcd4,stroke-width:2px classDef business fill:#f5f5f5,stroke:#666,stroke-width:2px class B,C,N,O config class E,F,G,H core class I,J,K,L,M scan class Q business
一、基本使用(含场景说明与注意事项)
MyBatis-Spring-Boot-Starter 简化了 MyBatis 与 Spring Boot 的整合,无需手动配置 SqlSessionFactory、SqlSession 等核心组件,仅需三步即可快速集成。
1. 依赖引入
在 Maven 项目的 pom.xml 中添加核心依赖,该依赖已内置 MyBatis 核心包、Spring 整合适配包及自动配置模块,无需额外引入其他关联依赖。
xml
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version> <!-- 稳定版,适配 Spring Boot 2.x 系列,如需适配 3.x 可升级至 3.0+ 版本 -->
</dependency>
2. YML 核心配置
通过 application.yml 配置 MyBatis 核心参数,指定配置文件路径和 Mapper 映射文件位置,支持通配符匹配多目录下的映射文件。
yaml
mybatis:
config-location: classpath:mybatis-config.xml # 指定 MyBatis 全局配置文件(如别名、插件、缓存等配置)
mapper-locations: classpath*:mapper/**/*.xml # 扫描类路径下所有 mapper 目录(含子目录)的 XML 映射文件
type-aliases-package: com.test.core.entity # 可选配置,指定实体类包路径,XML 中可直接使用类名(无需全限定名)
configuration:
map-underscore-to-camel-case: true # 可选配置,开启下划线命名转驼峰命名(如 user_name → userName)
3. 启动类配置
在 Spring Boot 启动类上添加 @MapperScan 注解,指定 Mapper 接口所在包路径,Spring 会自动扫描该包下的接口并创建代理对象。
java
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
// 开启 Spring Boot 自动配置,扫描当前包及子包下的组件
@SpringBootApplication
// 扫描 Mapper 接口所在包,多个包可通过逗号分隔(如 "com.test.core.mapper,com.test.ext.mapper")
@MapperScan(basePackages = "com.test.core.mapper")
public class TestApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
// 启动 Spring Boot 应用,加载所有自动配置和自定义组件
SpringApplication.run(TestApplication.class, args);
}
}
二、初始化流程(底层原理拆解)
Spring Boot 启动时,MyBatis 会通过自动配置机制完成核心组件的初始化,最终实现 Mapper 接口与 XML 映射文件的关联,核心是构建三大关键对象并注入 Spring 容器。
1. 核心初始化目标
初始化过程的核心是创建并组装三个核心对象,支撑 MyBatis 完整的 SQL 执行流程:
- SqlSessionFactory: MyBatis 核心工厂类,保存全局配置(数据源、映射文件、缓存策略等),负责创建 SqlSession 实例。
- SqlSessionTemplate: SqlSession 的 Spring 适配版(线程安全),封装了 SqlSession 的核心操作(CRUD),供业务代码直接调用。
- MapperScannerConfigurer: Mapper 接口扫描器,扫描指定包下的 Mapper 接口,为每个接口创建动态代理对象并注册到 Spring 容器。
2. SqlSessionFactory 与 SqlSessionTemplate 的注入流程
这两个组件的初始化依赖 Spring Boot 的自动配置机制,核心入口是 MybatisAutoConfiguration 类。
(1)自动配置类加载 引入 mybatis-spring-boot-starter 后,依赖会自带 mybatis-spring-boot-autoconfigure-2.1.0.jar。
Spring Boot 启动时,会通过 META-INF/spring.factories 文件中的配置,自动加载 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 这个自动配置类。
(2)SqlSessionFactory 构建
MybatisAutoConfiguration 类中通过 @Bean 注解声明 SqlSessionFactory,核心逻辑如下:
java
public class MybatisAutoConfiguration implements InitializingBean {
// 注入配置文件中的参数(对应 yml 中 mybatis 前缀的配置)
private final MybatisProperties properties;
// 注入数据源(由 Spring 自动配置,如 Druid、HikariCP 等)
private final DataSource dataSource;
// 其他依赖组件(拦截器、类型处理器等)
private final Interceptor[] interceptors;
private final List<ConfigurationCustomizer> configurationCustomizers;
// 构造方法自动注入依赖
public MybatisAutoConfiguration(MybatisProperties properties,
ObjectProvider<Interceptor[]> interceptorsProvider,
ObjectProvider<TypeHandler[]> typeHandlersProvider,
ResourceLoader resourceLoader,
ObjectProvider<DatabaseIdProvider> databaseIdProvider,
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
this.properties = properties;
this.interceptors = interceptorsProvider.getIfAvailable();
this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable(Collections::emptyList);
// 其他赋值逻辑...
}
// 构建 SqlSessionFactory 并注入 Spring 容器,@ConditionalOnMissingBean 表示用户未自定义时才生效
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
// 设置数据源
factory.setDataSource(dataSource);
// 设置 Mapper 映射文件路径(从配置文件中读取)
factory.setMapperLocations(resolveMapperLocations(properties.getMapperLocations()));
// 设置全局配置(如别名、下划线转驼峰等)
applyConfiguration(factory);
// 设置拦截器(如分页插件、日志插件等)
if (this.interceptors != null && this.interceptors.length > 0) {
factory.setPlugins(this.interceptors);
}
// 其他配置(类型处理器、数据库方言等)...
// 构建 DefaultSqlSessionFactory 实例并返回
return factory.getObject();
}
// 应用自定义配置(如通过 ConfigurationCustomizer 接口修改 MyBatis 配置)
private void applyConfiguration(SqlSessionFactoryBean factory) {
Configuration configuration = this.properties.getConfiguration();
// 若未指定 mybatis.config-location,则创建默认 Configuration 对象
if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
configuration = new Configuration();
}
// 执行自定义配置(用户可实现 ConfigurationCustomizer 接口扩展配置)
if (configuration != null && !this.configurationCustomizers.isEmpty()) {
for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
customizer.customize(configuration);
}
}
factory.setConfiguration(configuration);
}
// 构建 SqlSessionTemplate 并注入容器,依赖 SqlSessionFactory
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
// 默认为批量操作模式,可通过构造参数指定执行器类型(SIMPLE/REUSE/BATCH)
return new SqlSessionTemplate(sqlSessionFactory);
}
}
(3)Spring 事务整合
MyBatis 的事务由 TransactionFactory 接口管理,SqlSessionFactoryBean 的 buildSqlSessionFactory 方法中,会默认使用 SpringManagedTransactionFactory 适配 Spring 事务:
java
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
Configuration targetConfiguration = new Configuration();
// 配置环境:关联数据源和 Spring 事务工厂
targetConfiguration.setEnvironment(new Environment(
this.environment,
// 若未自定义事务工厂,默认使用 SpringManagedTransactionFactory
this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
this.dataSource
));
// 其他构建逻辑...
return new DefaultSqlSessionFactory(targetConfiguration);
}
这使得 MyBatis 可以无缝集成 Spring 的声明式事务(如 @Transactional 注解)。
3. MapperScannerConfigurer 的注入流程
Mapper 接口的扫描与代理对象创建,核心依赖 @MapperScan 注解和 MapperScannerRegistrar 类。
(1)注解触发扫描
@MapperScan 注解中通过 @Import(MapperScannerRegistrar.class) 导入扫描注册器,触发 Mapper 扫描逻辑:
java
// 可重复注解,支持多包扫描
@Repeatable(MapperScans.class)
@Import(MapperScannerRegistrar.class) // 导入扫描注册器
public @interface MapperScan {
String[] basePackages() default {}; // Mapper 接口所在包路径
Class<?>[] basePackageClasses() default {}; // 替代包路径,指定类所在包
// 其他属性(如 sqlSessionTemplateRef、sqlSessionFactoryRef 等)...
}
(2)注册 MapperScannerConfigurer
MapperScannerRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,在 Spring 容器初始化时,会动态注册 MapperScannerConfigurer 到容器:
java
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
private ResourceLoader resourceLoader;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 解析 @MapperScan 注解的属性(如 basePackages)
AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName())
);
// 注册 MapperScannerConfigurer 到 Spring 容器
registerBeanDefinitions(annoAttrs, registry, generateBeanName(annoAttrs, registry));
}
void registerBeanDefinitions(AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {
// 构建 MapperScannerConfigurer 的 BeanDefinition
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
// 设置扫描的包路径
builder.addPropertyValue("basePackage", StringUtils.arrayToCommaDelimitedString(annoAttrs.getStringArray("basePackages")));
// 设置 SqlSessionTemplate 的引用(默认使用容器中的 sqlSessionTemplate)
if (annoAttrs.hasAttribute("sqlSessionTemplateRef")) {
builder.addPropertyValue("sqlSessionTemplateBeanName", annoAttrs.getString("sqlSessionTemplateRef"));
}
// 设置 SqlSessionFactory 的引用(默认使用容器中的 sqlSessionFactory)
if (annoAttrs.hasAttribute("sqlSessionFactoryRef")) {
builder.addPropertyValue("sqlSessionFactoryBeanName", annoAttrs.getString("sqlSessionFactoryRef"));
}
// 其他配置(如标记接口、过滤器等)...
// 注册 BeanDefinition 到 Spring 容器
registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
}
// 其他辅助方法...
}
(3)Mapper 接口代理与注册
MapperScannerConfigurer 初始化后,会扫描 basePackages 下的所有 Mapper 接口,通过 MyBatis 的 MapperProxyFactory 为每个接口创建动态代理对象,最终将代理对象注册到 Spring 容器。
业务代码可直接通过 @Autowired 注入 Mapper 接口,实际调用的是代理对象,由代理对象通过 SqlSessionTemplate 执行 SQL。