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

相关推荐
实名上网宋凯宣2 小时前
Django
后端·python·django
利威尔xu4 小时前
Go IM 源码实战(14):本地缓存快 3000 倍,失效却难 10 倍
后端·缓存·微服务·面试·golang
逃逸线LOF5 小时前
Ribbon负载均衡原理(Irule组件、源码分析)
后端·spring cloud·ribbon
慢云智慧空间5 小时前
从设备智能到空间理解,空间智能终端解决方案商如何重新定义行业标准
后端
利威尔xu5 小时前
Go IM 源码实战(13):30 个会话只有 2 个红点,未读数错在三条路径
redis·后端·微服务·面试·golang
薛定谔的猫-菜鸟程序员6 小时前
软件架构设计师开发资料大全(从入门到精通)
后端·python·系统架构·flask·架构设计师
IT_陈寒7 小时前
SpringBoot多环境配置把我坑惨了,这个踩坑经验你最好看看
前端·人工智能·后端
码事漫谈8 小时前
DeepSeek 搞了个 "Super-agent",但不是超级智能
后端
吴凡wudianmei8 小时前
从 0 搭一个 AI Agent(四):SSE 跑通之后,三处“契约错配”与它们的修复边界
前端·后端·aigc
小兔子8 小时前
defer 的参数在写下那一刻就求值了,循环里这样写会踩坑
后端