从 @MapperScan 看 Spring 和 MyBatis 的整合

在 Spring Boot 中使用 Mybatis 时,会经常使用到一个注解 MapperScan,它可以指定对哪些包进行扫描(basePackages),将哪些类作为 Mapper 类(basePackageClasses),多数据源下的一些设置等,除了 basePackages 外,另一个重要的时 factoryBean,它的默认值是 MapperFactoryBean,这个属性在后续至关重要。

在 MapperScan 的注解上,还使用了 @Import,参数为 MapperScannerRegistrar,实际的 Bean 对象的注册是在该类中完成的。

在其 registerBeanDefinitions 的方法中,主要完成了以下几件事情:

  1. 生成一个MapperScannerConfigurerBeanDefinitionBuilder
  2. 对属性进行设置,其中重要的一点是在不指定 basePackages 属性时,它会获取当当前注解所在的类的全限定包。
  3. 在 Spring 容器中注册 MapperScannerConfigure

MapperScannerConfigure 实现了 BeanDefinitionRegistryPostProcessor ,它允许在 Bean 对象在注册过程中进行自定义操作,甚至注册更多的 Bean 对象。MapperScannerConfigure 实现了 postProcessBeanDefinitionRegistry 方法。简单来说,在该方法下会通过 ClassPathMapperScanner 读取到 basePackagesbasePackageClasses 等设置的所有的接口,将其注册到 Spring 容器内。

ClassPathMapperScanner 继承自ClassPathBeanDefinitionScanner,重写了 doScan 方法:

java 复制代码
@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);

    if (beanDefinitions.isEmpty()) {
        LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages)
                    + "' package. Please check your configuration.");
    } else {
        // 处理 Bean 对象的定义,实际上是对其属性进行设置
        processBeanDefinitions(beanDefinitions);
    }

    return beanDefinitions;
}

processBeanDefinitions 方法中,主要进行了以下操作:

  1. 设置实际的 beanClass 为注解中设置的 factoryBean,默认为MapperFactoryBean(也是该类属性的默认值)。
  2. 设置被代理的接口。
  3. 设置 sqlSessionTemplate 属性。

MapperFactoryBean 实现了 FactoryBean,在其简介中提到了实现了 FactoryBean 的类都是某个对象的获取工厂

Interface to be implemented by objects used within a {@link BeanFactory} which are themselves factories for individual objects. 】

也就是说在 Spring 容器进行依赖注入的时候,最终会调用 FactoryBean 的 getObject 获取实际的对象, MapperFactoryBean 的实现如下:

java 复制代码
@Override
public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
}

也就是使用了 MyBaits 原生的 getMapper 拿到接口的代理类,Spring 整合 MyBatis 的流程结束。

但是实际开发过程中是,会出现不写 MapperScan 的情况。

在这种情况下,利用 Spring 的 SPI 机制,自动注入 MybatisAutoConfiguration 类。该类除了基本的注入 SqlSessionFactory 和 SqlSessionTemplate 外,还会在未注入 MapperFactoryBeanMapperScannerConfigurer时,使用 AutoConfiguredMapperScannerRegistrar 进行自动注册。该类的大致流程也是先拿到 MapperScannerConfigurerBeanDefinitionBuilder ,然后设置其属性,最后注册到 Spring Boot 的容器中。

关注公众号:KeepLoving 一起学习更多源码知识。

相关推荐
桦说编程3 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
lifallen3 小时前
Java Stream sort算子实现:SortedOps
java·开发语言
IT毕设实战小研3 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
记忆不曾留4 小时前
Mybatis 源码解读-SqlSession 会话源码和Executor SQL操作执行器源码
mybatis·二级缓存·sqlsession会话·executor执行器·一级缓存localcache
没有bug.的程序员4 小时前
JVM 总览与运行原理:深入Java虚拟机的核心引擎
java·jvm·python·虚拟机
甄超锋4 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国5 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Zyy~5 小时前
《设计模式》装饰模式
java·设计模式
A尘埃5 小时前
企业级Java项目和大模型结合场景(智能客服系统:电商、金融、政务、企业)
java·金融·政务·智能客服系统
青云交5 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵治理与出行效率提升中的应用(398)
java·大数据·flink·大数据可视化·拥堵预测·城市交通治理·实时热力图