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

相关推荐
短剑重铸之日1 小时前
《ShardingSphere解读》07 读写分离:如何集成分库分表+数据库主从架构?
java·数据库·后端·架构·shardingsphere·分库分表
wefly20172 小时前
m3u8live.cn 在线M3U8播放器,免安装高效验流排错
前端·后端·python·音视频·前端开发工具
zhanggongzichu3 小时前
小白怎么理解后端分层概念
后端·全栈
stark张宇4 小时前
Golang后端面试复盘:从Swoole到IM架构,如何支撑360w用户的实时消息推送?
后端
小码哥_常4 小时前
从0到1:搭建Spring Boot 3企业级认证授权平台
后端
小码哥_常4 小时前
告别扫库噩梦!Spring Boot+Redis让订单超时管理飞起来
后端
大傻^4 小时前
Spring AI Alibaba 快速入门:基于通义千问的AI应用开发环境搭建
java·人工智能·后端·spring·springai·springaialibaba
IT_陈寒5 小时前
SpringBoot实战:3个隐藏技巧让你的应用性能飙升50%
前端·人工智能·后端
彭于晏Yan6 小时前
MQTT消息服务
spring boot·后端·中间件
程序员Sunday6 小时前
Claude Code 生态爆发:5个必知的新工具
前端·人工智能·后端