要想知道Mybatis 如何与Spring 框架整合在一起,首先得思考以下几个问题:

1、定义的Mapper接口是怎样被“实现”的?

2、Mapper接口是怎么被Spring发现的,又是怎样被注入到Spring Context 里的?

3、Spring 是怎样通过接口名称找到实现具体Mapper 接口的代理的?

4、这个代理有是怎样找到Mapper的配置文件的?

5、找到了配置文件,又是怎样将接口定义的方法与配置文件一一对应的?

6、配置文件又是如何被解析出来,变成具体的Sql实现的?

7、数据源又是如何被Spring注入的?

开始阅读源代码,思考怎样实现?

1、定义的Mapper接口,使用Spring的主键例如@Autowired 或者@mapper 都能自动被代理,通过接口名,既Spring Context里标识的Bean ID ,注入了代理的对象,框架自己实现InvocationHandler 。 

  •  Spring怎样找到你的Mapper接口类?指定包路径,通过继承ClassPathBeanDefinitionScanner实现自己的Bean定义扫描,加载自己的类,然后就能知道 Mapper 的接口和定义的 方法
  • 那mapper的SQL配置文件是如何与Mapper 类关联的?要保证配置文件的映射空间是mapper的全路径,方法名称既是配置文件的ID,这样就能 将 mapper的sql定义与 接口一一映射了,配置文件的每个id 对应每一个方法。

Mybatis 如何与Spring 容器整合在一起的

       图中有【MapperScan】自定义的注解,就是要加载自定义的mapper bean definition 到spring 容器的,

  (1)但是Spring 怎样会加载我们自己定义的注解呢?

 通过@Configuration注解,这个会被Spring 扫描到,然后发现了我们的注解@MapperScan

 (2)加载了这个注解之后,Spring又是怎么来知道@mapperScan是来干什么的?

得模仿@Autowired注解的实现,Autowired会将扫描类下面的每个非静态字段或者setter方法,看看有没有这个注解,若有,将会通过字段的类型去spring容器里找到实现(本质也是代理)并注入,这样就能引入了,

Mybatis 如何与Spring 容器整合在一起的

(3)怎样让Spring 加载自己自定义的注解?

这就是在@MapperScan中加入Spring的注解@Import ,既是导入一个配置类MapperScannerRegister

这个类会被Spring加载,Spring发现他实现了ImpoerBeanDefinitionRegistar这个接口,就会调用这个registerBeanDefinition的方法,顾名思义就是按照Spring的规则,注册自己的bean definition到Spring 的***中【BeanDefinitionRegister】

(4)怎样找到了mapper? 

在注册Bean 定义的方法里,他能找到已经注册的@mapperSacan这个注解,从而找到这个注解里面的数据是指定了Mapper的路径,找到了 mapper ,使用自己实现的类扫描去扫描这个路径,加载mapper,在这里来一个一个的去注册mapper代理

Mybatis 如何与Spring 容器整合在一起的

(5)又是怎样将mapper 注册到 spring 容器中?

下面就是自己实现的类扫描ClassPathMapperScanner,继承自Spring原生的ClassPathBeanDefinition,这就是开始注册自己的bean ,在这里发现获取到spring 给的【mapper的原生的类定义】后,类名没有修改【ID没有修改】但是将类修改成了MapperFactoryBean, 【修改了具体的实现】

过构造器注入了原来的mapper的类名,下面开始往MapperFactoryBean里注入数据源等属性,

这就是Spring bean 定义的修改器。

Mybatis 如何与Spring 容器整合在一起的

(6)既然通过mapper类名这个ID, 找到的是MapperFacttoryBean ,那这个类有什么用呢?

    其实这个bean只是一个工厂方法,实现了Spring 定义的FactoryBean,所有得调用他的getObject()方法,才是真正注入的对象。

    截图中,Spring发现这个bean是一个 工厂bean,会直接获取它真实的 bean.

Mybatis 如何与Spring 容器整合在一起的

Mybatis 如何与Spring 容器整合在一起的

Mybatis 如何与Spring 容器整合在一起的

 小段总结:

通过@Configuration @Import【spring 原生的注解】往spring容器里加载了自己自定义的注解 

@mapperScan【告诉mapper在哪里】和【MapperScanRegistar】导入bean定义的类【将mapper的bean definition 注入到Spring容器中,ID 是接口名,类是mapperFactoryBean,工厂方法,真实的对象是sqlSession.getMapper(mapper接口类) 】

(7)sqlSession是哪里来的?他主要干了什么?

   首先这个sqlSession是SqlSessionFactory或者是SqlSessionTemplate,在第一张图中就已经通过@bean 加入了Spring 容器。

  主要工作是解析mapper配置的xml文件,并保存。key 就是 接口类。

    Mybatis 如何与Spring 容器整合在一起的

  (8)那这个sqlSession.getMapper(mapper接口类) 返回的对象是什么呢?

      发现每个Mapper 都映射成MapperProxyFactory,  顾名思义就是mapper的代理工厂,具体的对象就是返回一个代理对象。

     所以,最后具体实现方法的是handder =>【MapperProxy】通过Method 找到=>MapperMethod

   每个mapper 的方法都映射成一个MapperMethod.  MapperMethod 有sqlCommand ,有他来执行方法。

       Mybatis 如何与Spring 容器整合在一起的  Mybatis 如何与Spring 容器整合在一起的

Mybatis 如何与Spring 容器整合在一起的

Mybatis 如何与Spring 容器整合在一起的

最后总结

 1、定义的Mapper接口是怎样被“实现”的?

2、Mapper接口是怎么被Spring发现的,又是怎样被注入到Spring Context 里的?

自定义的注解加载了mapper到Spring 容器,ID 是接口名,注入的具体类是一个动态的代理对象.

被调用时,真正处理任务的是 hander 【MapperProxy】

3、Spring 是怎样通过接口名称找到实现具体Mapper 接口的代理的?

添加了Spring的注解@Autowired 通过类名【ID】在Spring容器里找到的bean definition.

6、配置文件又是如何被解析出来,变成具体的Sql实现的?

7、数据源又是如何被Spring注入的?

4、这个代理又是怎样找到Mapper的配置文件的?

 Spring加载了SqlSessionFactory ,注入了数据源,此时mybatis的数据源就交给了Spring注入,在这里定义了配置文件。

       最后也是通过这个方法注入的:sqlSession.getMapper(mapper接口类) 

5、找到了配置文件,又是怎样将接口定义的方法与配置文件一一对应的?

 配置文件映射的空间 应该是 mapper 类路径。


写在最后,想怎样实现自己的注解,可以参考Spring 自定义的注解实现。
思绪和排版一样有点混乱。
 


相关文章:

  • 2022-12-23
  • 2021-09-12
  • 2021-12-30
  • 2021-06-19
  • 2021-04-06
  • 2021-12-13
猜你喜欢
  • 2022-02-20
  • 2021-07-19
  • 2021-10-14
  • 2021-10-31
  • 2021-07-19
  • 2022-01-23
相关资源
相似解决方案