要想知道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 。
图中有【MapperScan】自定义的注解,就是要加载自定义的mapper bean definition 到spring 容器的,
通过@Configuration注解,这个会被Spring 扫描到,然后发现了我们的注解@MapperScan
得模仿@Autowired注解的实现,Autowired会将扫描类下面的每个非静态字段或者setter方法,看看有没有这个注解,若有,将会通过字段的类型去spring容器里找到实现(本质也是代理)并注入,这样就能引入了,
这就是在@MapperScan中加入Spring的注解@Import ,既是导入一个配置类MapperScannerRegister
这个类会被Spring加载,Spring发现他实现了ImpoerBeanDefinitionRegistar这个接口,就会调用这个registerBeanDefinition的方法,顾名思义就是按照Spring的规则,注册自己的bean definition到Spring 的注册机中【BeanDefinitionRegister】
在注册Bean 定义的方法里,他能找到已经注册的@mapperSacan这个注解,从而找到这个注解里面的数据是指定了Mapper的路径,找到了 mapper ,使用自己实现的类扫描去扫描这个路径,加载mapper,在这里来一个一个的去注册mapper代理
下面就是自己实现的类扫描ClassPathMapperScanner,继承自Spring原生的ClassPathBeanDefinition,这就是开始注册自己的bean ,在这里发现获取到spring 给的【mapper的原生的类定义】后,类名没有修改【ID没有修改】但是将类修改成了MapperFactoryBean, 【修改了具体的实现】
通过构造器注入了原来的mapper的类名,下面开始往MapperFactoryBean里注入数据源等属性,
这就是Spring bean 定义的修改器。
其实这个bean只是一个工厂方法,实现了Spring 定义的FactoryBean,所有得调用他的getObject()方法,才是真正注入的对象。
截图中,Spring发现这个bean是一个 工厂bean,会直接获取它真实的 bean.
通过@Configuration @Import【spring 原生的注解】往spring容器里加载了自己自定义的注解
@mapperScan【告诉mapper在哪里】和【MapperScanRegistar】导入bean定义的类【将mapper的bean definition 注入到Spring容器中,ID 是接口名,类是mapperFactoryBean,工厂方法,真实的对象是sqlSession.getMapper(mapper接口类) 】
首先这个sqlSession是SqlSessionFactory或者是SqlSessionTemplate,在第一张图中就已经通过@bean 加入了Spring 容器。
主要工作是解析mapper配置的xml文件,并保存。key 就是 接口类。
发现每个Mapper 都映射成MapperProxyFactory, 顾名思义就是mapper的代理工厂,具体的对象就是返回一个代理对象。
所以,最后具体实现方法的是handder =>【MapperProxy】通过Method 找到=>MapperMethod
每个mapper 的方法都映射成一个MapperMethod. MapperMethod 有sqlCommand ,有他来执行方法。
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 类路径。