1. 源码分析系列——mybatis源码分析

发布于 2022年 04月 09日 17:10

腾讯服务器

88 / 年

  • 上海/北京/广州...
  • 2核 2G 4M
  • Linux/Windows
新年大优惠

腾讯服务器

425 / 年

  • 上海/北京/广州...
  • 4核 8G 10M
  • Linux/Windows
年度最便宜

腾讯服务器

1249 / 年

  • 上海/北京/广州...
  • 8核 16G 14M
  • Linux/Windows
点击查看

代码直接引用 juejin.cn/post/684490… demo代码,由于没有经历过手动连接数据库的时代,不知道具体流程是啥,debug看吧。

此篇主要看下插入操作的大体流程,之后的篇章会做具体分析

  1. 首先在插入方法处打断点,开始执行

  1. 可以看到userMapper被代理了

  1. 进入insert方法

  1. 继续执行,走到cachedInvoker这步,进入

  1. 计算此method是否为缓存方法

  1. m 就是刚才的insert方法,我们进入isDefault方法中看下,此方法判断是否为在接口中声明的带有方法体的非抽象实例方法(这里感觉有问题,interface有方法体的方法不就是抽象方法吗,回头再研究下)

// ****************************** todo ******************************

  1. 上边问题还没解决,先继续

  1. 这里我们看到了这个方法,获取数据库配置,从这里我们可以一路回溯点击找到加载配置的起点(当然这是我看代码的流程,你如果知道mybatis怎么加载运行的可以直接从头看起)

  1. 经过一路漫长的点点点,我们找到了此方法,sqlSessionFactory

  1. 可以看到这个方法所在的类实现了InitializingBean接口

InitializingBean接口的作用:InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候,在所有的properties被注入后都会执行该方法

  1. 此类的 afterPropertiesSet 方法做了一些检查工作,我们可以先略过

  1. 继续看我们的主角sqlSessionFactory,通过注解可以看到此方法的执行时机是@ConditionalOnMissingBean,此方法做了一系列的设置工作,包括各种数据库连接参数,driver,language level等

  2. 进入getObject方法

  1. 通过afterPropertiesSet初始化SqlSessionFactory

  1. 进入buildSqlSessionFactory方法,可以看到此方法设置了一系列的config,targetConfiguration,用来构建一个默认的SqlSessionFactory实例,此时mybatis的配置已设置完成

初始化配置文件信息的本质就是创建Configuration对象,将解析的xml数据封装到Configuration内部的属性中。

  1. 9 ~ 15 是mybatis配置的加载过程,接下来我们继续从8开始,进入new MapperMethod()

  1. 顾名思义,通过方法名我们知道此方法是用来设置sql的

  1. 通过debug看到此sql的类型是INSERT

  1. 经过一系列设置操作后,终于该轮到执行了,进入PlainMethodInvoker方法

  1. 通过以下构造函数,我们得到了一个MapperMethodInvoker接口的实例PlainMethodInvoker

  1. 回到4

  1. 进入invoke方法

  1. 进入execute方法,可以看到这里是mybatis执行调用的地方

  1. 我们现在是insert方法,进入convertArgsToSqlCommandParam方法看下

  1. 得到的param就是我们的测试数据

  1. 进入insert方法

SqlSession: SqlSession中的两个最重要的参数,configuration与初始化时的相同,Executor为执行器
  • SqlSession是一个接口,它有两个实现类:DefaultSqlSession(默认)和SqlSessionManager(弃用,不做介绍)
  • SqlSession是MyBatis中用于和数据库交互的顶层类,通常将它与ThreadLocal绑定,一个会话使用一个SqlSession,并且在使用完毕后需要close
Executor也是一个接口,他有三个常用的实现类:
  • BatchExecutor(重用语句并执行批量更新)
  • ReuseExecutor(重用预处理语句prepared statements)
  • SimpleExecutor(普通的执行器,默认)
  1. buildAllStatements方法,引用下翻译:解析缓存中所有未处理的语句节点。建议一旦添加了所有映射器,便调用此方法,因为它提供了快速失败语句验证

  1. 回到26我们得到一个MappedStatement

  1. 接下来进入update方法

  1. BaseExecutor.update

  1. SimpleExecutor.doUpdate

  1. SimpleExecutor.prepareStatement

  1. RoutingStatementHandler.prepare

  1. 这里可以进去看下最终需要执行的sql

  1. RoutingStatementHandler.parameterize

  2. PreparedStatementHandler.parameterize

  1. 看下prepareStatement最终得到的声明

  1. 回到31进入RoutingStatementHandler.update

  1. 进入PreparedStatementHandler.update

  1. HikariProxyCallableStatement.execute

  1. ClientPreparedStatement.execute

  1. ClientPreparedStatement.executeInternal, 此方法是真正执行准备好的sql的方法

  1. 最后SimpleExecutor.doUpdate关闭资源

推荐文章