首先简单介绍下FactoryBean的作用:当实现FactoryBean接口的类注册到Spring容器中时,通过getBean()获取对象时,底层实现实际上是调用FactoryBean接口的getObject()获取内部的对象;

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_mybatis

        在SpringBoot中有一个默认的配置类MybatisAutoConfiguration,默认扫描根目录下的所有的类,默认使用了@Mapper注解作添加到IncludeFilter中,找到对应的Dao,然后通过 BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry); 将对应的Dao注入到容器中;

       第二种方式使用@MapperScan(basePackages="com.hua.springboot.dao")指定需要扫描包的路径,此时在MapperScan注解中引入一个MapperScannerRegistrar,这个类实现了ImportBeanDefinitionRegistrar接口,所以调用registerBeanDefinitions可以注册bean信息。

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_spring boot_02

            具体扫描到对应的Dao,并且将该Dao以beanName,BeanDefinition的形式注册到beanDefinitionMap中后;最重要的地方在于注册到beanDefinitionMap后将dao对应的BeanDefinition转化成MapperFactoryBean的BeanDefinition存到Map中;这个过程就是在processBeanDefinitions()中实现;

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_spring boot_03

            首先循环所有注册后的Dao的beanDefinition,然后对每个BeanDefinition进行加工处理,如下图,在MapperMapFactoryBean中通过构造器传入对应的Dao接口的方式动态加载了所有的Dao。这样通过扫描的方式+构造器注入转化的方式用一个MapperMapFactoryBean就可以注册所有的Dao,减少了一个个配置Dao的过程。

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_spring_04

       目前为止,我们已经实现了将Dao注册到容器中的过程,但是我们知道Mybatis是通过动态代理的方式将Dao的接口实现的,那么这个动态代理对象又是如何创建的呢,这个容器中的FactoryBean是如何和动态代理对象绑定的呢?

         在Ioc容器实例化所有的BeanDefinition过程中,MapperFactoryBean在初始化的时候调用了checkDaoConfig()方法,该方法就给Dao的接口创建了一个代理对象工厂,同时存在MapperRegistry的Map<Class<?>, MapperProxyFactory<?>>knownMappers 中缓存起来。注意此时只做了绑定并未产生对应的代理对象。

        

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_spring boot_05

              在Ioc容器创建FactoryBean类型的bean过程中,需要返回的是FactoryBean的 getObject();是由以下的方法getObjectForBeanInstance()实现的:该方法最终调用了FactoryBean的 getObject();

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_mybatis_06

           在MapMapperFactoryBean的getObject()中,通过传入接口作为参数调用getMapper()生成代理对象。getMapper()的最底层实现是通过取出之前初始化MapMapperFactoryBean的缓存knownMappers,创建代理对象;然后将具体接口和对应的代理对象存放在factoryBeanObjectCache 缓存中。

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_缓存_07

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_动态代理_08

          至此整个Springboot整合Mybatits的代理对象的过程都完成了,在我们的程序调用Dao接口时,通过getBean()获取对应的代理对象时,就会从factoryBeanObjectCache拿出缓存的代理对象;

 

         最后总结下大致的流程:

创建springboot配置mybatisplus代码生成器 springboot整合mybatis源码_缓存_09