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

相关推荐
王道长AWS_服务器4 小时前
AWS Elastic Load Balancing(ELB)—— 多站点负载均衡的正确打开方式
后端·程序员·aws
oak隔壁找我4 小时前
Spring BeanFactory 和 FactoryBean 详解
后端
用户4099322502124 小时前
只给表子集建索引?用函数结果建索引?PostgreSQL这俩操作凭啥能省空间又加速?
后端·ai编程·trae
oak隔壁找我4 小时前
SpringMVC 教程
后端
用户34325962788164 小时前
Spring AI Alibaba中使用Redis Vector报错修改过程
后端
oak隔壁找我4 小时前
MyBatis和SpringBoot集成的原理详解
后端
oak隔壁找我4 小时前
SpringBoot @Import 注解详解
后端
oak隔壁找我4 小时前
Spring Bean 生命周期详解
后端
Tony Bai5 小时前
【Go 网络编程全解】06 UDP 数据报编程:速度、不可靠与应用层弥补
开发语言·网络·后端·golang·udp