Spring整合MyBatis:MapperScannerConfigurer 原理

MapperFactoryBean

使用 MapperFactoryBean 可以向 Spring 容器中导入一个 Mapper 接口的代理实现类

如:向 Spring 容器中导入 com.springdemo.dao.UserDao 接口的代理实现类

<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.spring-mybatis.dao.UserDao"/>   <!-- 要代理的目标接口 -->
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

这样的配置其实是向 Spring 容器中注入了一个 MapperFactoryBean ,而 MapperFactoryBean 是一个 FactoryBean ,当获取 userDao 时,其实调用的是 MapperFactoryBean 的 getObject() 方法进行的获取。

在这里插入图片描述

  • 注:因为 MapperFactoryBean 是 SqlSessionDaoSupport 的子类,所以要为其配置 sqlSessionFactory 来构建成员属性 SqlSessionTemplate ,同时在 MapperFactoryBean 类中可以通过 getSqlSession() 方法来获取这个 SqlSessionTemplate,【关于MapperFactoryBean、SqlSessionDaoSupport 的详细介绍,可以看上一篇文章

注意到,通过配置 MapperFactoryBean 的方式,只能向容器中注入一个接口代理对象
当有很多 DAO 接口时,就需要为每一个 DAO 接口配置 MapperFactoryBean:

<bean id="catDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.spring-mybatis.dao.CatDao"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="dogDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.spring-mybatis.dao.DogDao"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="studentDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.spring-mybatis.dao.StudentDao"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
....

这种方式显然是很低效的,为了解决这个问题,我们使用 MapperScannerConfigurer,让它扫描一个包下的所有接口,成批地向容器中注入接口代理对象

MapperScannerConfigurer

MapperScannerConfigurer 可以为一个包下的所有 Mapper 接口创建代理,并注入Spring 容器

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<!--指定Mapper接口所在的包-->
	<property name="basePackage" value="com.spring-mybatis.dao" />
</bean>

使用这种方式,com.spring-mybatis.dao 包下的所有 DAO 接口,Spring 都会为其创建代理对象并注入容器

原理:

可以看到 MapperScannerConfigurer 实现了 BeanDefinitionRegistryPostProcessor接口
(实现其 postProcessBeanDefinitionRegistry() 方法可以向容器中注册 BeanDefinition)。

关注 MapperScannerConfigurer 对 postProcessBeanDefinitionRegistry 方法的实现:
在这里插入图片描述

进入 scan() 方法:
在这里插入图片描述

进入 doScan():
在这里插入图片描述
进入 processBeanDefinitions() : 处理这些 Mapper 接口所对应的 BeanDefinition:
在这里插入图片描述

可以看到:

1、MapperScannerConfigurer 利用 ClassPathMapperScanner 扫描 basePackage 包下的 Mapper 接口,将这些 Mapper 接口解析成一个个 BeanDefinition。

2、由于接口不能直接创建对象,所以在处理 BeanDefinition 的过程中,将这些 BeanDefinition 的 BeanClass 类型设置成了 MapperFactoryBean 类型。所以后续 Spring 在依据 BeanDefinition 创建对象时,实际上创建的是一批 MapperFactoryBean 对象。

3、这些 MapperFactoryBean 的构造函数中传入的值是 Mapper 接口的类名(相当于为我们自动配置了 MapperFactoryBean 的 mapperInterface 属性)

4、同时设置了自动装配的类型为按类型注入,这说明这些 MapperFactoryBean 在创建的过程中,Spring 会为类中的 Set 方法注入相应类型的 Bean(这也就是为什么在配置 MapperScannerConfigurer 时,无需为其配置 SqlSessionFactory 的原因)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值