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的核心机制。

相关推荐
章豪Mrrey nical7 小时前
前后端分离工作详解Detailed Explanation of Frontend-Backend Separation Work
后端·前端框架·状态模式
派大鑫wink8 小时前
【JAVA学习日志】SpringBoot 参数配置:从基础到实战,解锁灵活配置新姿势
java·spring boot·后端
程序员爱钓鱼8 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
xUxIAOrUIII8 小时前
【Spring Boot】控制器Controller方法
java·spring boot·后端
Dolphin_Home8 小时前
从理论到实战:图结构在仓库关联业务中的落地(小白→中级,附完整代码)
java·spring boot·后端·spring cloud·database·广度优先·图搜索算法
zfj3218 小时前
go为什么设计成源码依赖,而不是二进制依赖
开发语言·后端·golang
weixin_462446238 小时前
使用 Go 实现 SSE 流式推送 + 打字机效果(模拟 Coze Chat)
开发语言·后端·golang
JIngJaneIL9 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
小信啊啊9 小时前
Go语言切片slice
开发语言·后端·golang
Victor35611 小时前
Netty(20)如何实现基于Netty的WebSocket服务器?
后端