MyBatis的MapperFactoryBean详解

MyBatis的MapperFactoryBean详解

1. 基本概念

MapperFactoryBean 是MyBatis与Spring框架集成的核心组件,它实现了Spring的FactoryBean接口,负责将MyBatis的Mapper接口转换为可被Spring容器管理的Bean。当我们在Spring中直接注入Mapper接口时,实际上注入的是MapperFactoryBean创建的Mapper接口的动态代理实现。

2. 工作原理

MapperFactoryBean的核心工作原理可以概括为以下几点:

  1. 实现FactoryBean接口 :通过getObject()方法返回Mapper接口的代理实现
  2. 继承SqlSessionDaoSupport:获取SqlSession实例,用于执行SQL操作
  3. 动态代理机制:使用JDK动态代理为Mapper接口创建实现类
  4. SQL执行封装:将Mapper接口方法调用转换为对应的SQL执行

关键代码流程

MapperFactoryBean在初始化过程中,会:

  1. 设置SqlSessionFactory,构建SqlSessionTemplate
  2. 检查Mapper接口配置
  3. 通过SqlSession的getMapper方法创建接口的代理实现
java 复制代码
// SqlSessionDaoSupport中的核心代码
bublic void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (!this.externalSqlSession) {
        this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }
}

// MapperFactoryBean继承自SqlSessionDaoSupport,重写getObject方法
public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
}

3. 配置方式

XML配置方式

最传统的MapperFactoryBean配置如下:

xml 复制代码
<!-- 配置单个Mapper接口 -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.example.mapper.UserMapper" />
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

批量注册方式

当Mapper接口较多时,可以使用MapperScannerConfigurer进行批量注册:

xml 复制代码
<!-- 批量扫描Mapper接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.example.mapper" />
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

Spring Boot配置方式

在Spring Boot中,通常使用注解方式简化配置:

java 复制代码
@Configuration
@MapperScan("com.example.mapper")
public class MyBatisConfig {
    // 配置相关Bean...
}

4. MapperFactoryBean与SqlSessionTemplate的关系

MapperFactoryBean继承自SqlSessionDaoSupport,而SqlSessionDaoSupport中使用SqlSessionTemplate作为SqlSession的实现。SqlSessionTemplate是线程安全的,它内部使用SqlSessionInterceptor代理模式,保证每个方法调用都使用正确的SqlSession实例。

java 复制代码
// SqlSessionTemplate内部的代理实现
private class SqlSessionInterceptor implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 获取或创建SqlSession
        final SqlSession sqlSession = getSqlSession(...);
        try {
            // 调用目标方法
            Object result = method.invoke(sqlSession, args);
            // 处理事务...
            return result;
        } finally {
            // 正确关闭SqlSession
        }
    }
}

5. 核心参数说明

MapperFactoryBean主要有两个核心参数:

  1. mapperInterface:指定要代理的Mapper接口
  2. sqlSessionFactory:指定使用的SqlSessionFactory实例

其他可选参数包括:

  • addToConfig:是否将Mapper接口添加到MyBatis配置中(默认true)
  • sqlSessionTemplate:可以直接设置SqlSessionTemplate而非SqlSessionFactory

6. 优势与应用场景

主要优势

  1. 简化开发:无需手动编写Mapper接口的实现类
  2. Spring集成:无缝集成Spring的依赖注入和事务管理
  3. 线程安全:通过SqlSessionTemplate确保线程安全
  4. 灵活配置:支持单接口配置和批量扫描

应用场景

  1. 所有使用MyBatis与Spring集成的项目
  2. 需要将MyBatis Mapper接口作为Spring Bean管理的场景
  3. 需要利用Spring的事务管理功能执行MyBatis操作的场景

7. 与MapperScannerConfigurer的对比

特性 MapperFactoryBean MapperScannerConfigurer
配置方式 单个接口配置 批量扫描配置
使用复杂度 配置较多(每个接口都需要单独配置) 配置简单(一次性配置整个包)
适用场景 少量Mapper接口 大量Mapper接口
灵活性 更高(可针对每个Mapper单独配置) 较低(统一配置)

8. 实际应用示例

完整的MyBatis与Spring集成配置

xml 复制代码
<!-- 1. 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/test" />
    <property name="username" value="root" />
    <property name="password" value="root" />
</bean>

<!-- 2. 配置SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations" value="classpath:mapper/*.xml" />
    <property name="typeAliasesPackage" value="com.example.model" />
</bean>

<!-- 3. 方式一:单独配置MapperFactoryBean -->
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.example.mapper.UserMapper" />
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<!-- 或者方式二:批量扫描配置 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.example.mapper" />
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

<!-- 4. 配置Service,注入Mapper -->
<bean id="userService" class="com.example.service.UserServiceImpl">
    <property name="userMapper" ref="userMapper" />
</bean>

9. 总结

MapperFactoryBean是MyBatis与Spring集成的关键组件,它巧妙地利用了Spring的FactoryBean机制,使MyBatis的Mapper接口能够作为Spring Bean被管理和注入。在实际开发中,特别是使用XML配置的项目中,MapperFactoryBean是连接MyBatis和Spring的重要桥梁。而在Spring Boot项目中,虽然@MapperScan注解简化了配置,但底层仍然依赖于MapperFactoryBean的核心机制。

相关推荐
我命由我123455 分钟前
Java 并发编程 - Delay(Delayed 概述、Delayed 实现、Delayed 使用、Delay 缓存实现、Delayed 延迟获取数据实现)
java·开发语言·后端·缓存·java-ee·intellij-idea·intellij idea
我是天龙_绍1 小时前
java 比对两对象大小 重写 comparator
后端
IT_陈寒1 小时前
Python 3.12新特性实测:10个让你的代码提速30%的隐藏技巧 🚀
前端·人工智能·后端
BingoGo1 小时前
从零开始打造 Laravel 扩展包:开发、测试到发布完整指南
后端·php
9号达人2 小时前
普通公司对账系统的现实困境与解决方案
java·后端·面试
golang学习记2 小时前
Go 1.26 新特性:netip.Prefix.Compare —— 标准化 IP 子网排序能力
后端
花落已飘2 小时前
openEuler容器化实践:从Docker入门到生产部署
后端
Cache技术分享2 小时前
233. Java 集合 - 遍历 Collection 中的元素
前端·后端
回家路上绕了弯2 小时前
五分钟内重复登录 QQ 号定位:数据结构选型与高效实现方案
分布式·后端