手撕JAVA(三十一)手撕Mybatis底层源码
以上是一个标准的原生mybatis的工作流程,最关键的步骤是:
1.创建SqlSessionFactory
2.获取SqlSession
3.获取动态代理对象(mapperProxy)
3.执行方法
本文将按照以上一个mybatis的标准工作流程来拆解mybatis的底层源码。
开始阅读源码之前,先建立三个概念,不然会对阅读造成极大障碍:
1.mybatis有四大对象:executor、StatementHandler、ParamterHandler、ResultHandler
2.mybatis底层封装的是JDBC,其实底层与数据库交互的仍然是原生的JDBC
3.mybatis以xml配置文件来完成开发者与框架的交互,所以整个流程其实就是对配置文件的不断解析与包装。
1.创建SqlSessionFactory
返回一个DefaultSessionFactory,里面包含一个configuration
创建SqlSessionFactory其实就是将xml中的配置文件解析出来,存入configuration类中去。
mybatis的xml配置文件有两类:
1.全局配置文件:用来做全局配置
2.是mapper配置文件:用来写SQL
具体过程就是调用各种解析器去解析这两类xml中的标签
configuration类中的属性其实就是包含了配置文件中各种可能出现的标签
configuration的成员变量中一个名叫mappedStatements的Map中以KV对的形式存放有mapper.xml的解析结果,key是sql标签中的id值,value是MappedStatement对象
一个MappedStatement对象就是mapper.xml中一个sql标签的解析结果。
获取SqlSession
返回DefaultSqlSession,里面包含configuration和executor
获取SqlSession这其实就是根据configuration来创建executor
executor会在这一步被创建,并根据配置文件中的配置解析结果被层层包装。
获取mapperProxy
configuration中除了mappedStatement外还有个重要的属性——mapperRegistry。
mapperRegistry中包含一切与mapper动态代理相关内容。其中的knowMappers属性
是以KV对的形式存储了每个mapper接口及其MapperProxyFactory。
mapperProxyFactory是用于生产代理对象的工厂类。
之所以每个mapper都会有单独的一个mapperProxyFactory,而不使用一个总的工厂类来生产代理对象是因为:
1.需要将xml中的sql标签与mapper的方法做关联。这样才能实现在invoke接口的method的时候执行相应的sql标签中的SQL内容。
2.两者的映射关系存放在mapperProxyFactory中的methodCache中。
3.具体封装过程为在mapperProxy的invoke方法中将method封装为一个新的cacheMethod类放入mapperProxyFactory的cacheMethod中。
备注:其实cacheMethod类中有三个属性:1.接口 2.
mapperProxyFactory的源码:
封装两个属性:
- 对应mapper接口
- mapper接口方法和xml文件SQL标签的映射关系map
mapperProxy的源码:
执行方法
总体流程
executor负责执行、其实是调用的statementHandler
statementHandler负责预编译、参数处理,其实是调用的ParamterHandler和ResultsetHandler
ParamterHandler负责参数处理、ResultsetHandler负责JAVA类与数据库类之间的映射。
详细流程
1.调用代理对象方法,
首先在mapperProxy中将所调用方法封装为cacheMapperMethod对象。改对象中包含
应接口的引用、当前所调用方法的引用、configuration以及sqlSession的引用。
2.交给executor执行:
代理对象又调用sqlSession中的executor去执行。在执行前会先通过method名字去configuration中拿到对应的MappedStatement.MappedStatement中包含xml中一个SQL标签的全部信息。然后会处理参数调用之前看过的参数处理流程的源码,单个(包括单实体类)就返回,多个就封装为map。
3.判断缓存
在真正执行之前还会判断本次查询在缓存中是否存在。存在的话直接去缓存中拿,不存在的话executor再继续往下执行。
4.底层调用JDBC
最后executor底层其实就是封装的原生JDBC的statement等组件。
流程总结
1.将配置文件解析为Configuration对象,创建一个DefaultSqlSessionFactory对象
里面包含Configuration
2.创建一个DefaultSqlSession对象
里面包含Configuration、executor
1.拿到Mapper接口对应的MapperProxy
2.执行增删改查方法
调用DefaultSqlSession来执行
DefaultSqlSession调用自己里面的executor来执行
创建Statementhandler、ParameterHandler、ResultHandler
Statementhandler负责预编译,
statementhandler调用ParameterHandler来设置参数、
调用ResultHandler来封装结果(做数据库与JAVABean的映射)