IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 我的同事妹妹深夜来我家问我MyBatis源码解析,我是这样给她讲的 -> 正文阅读

[Java知识库]我的同事妹妹深夜来我家问我MyBatis源码解析,我是这样给她讲的

前言

不积跬步无以至千里,不积小流无以成江海

各位好,骚气的我又来了。猜猜今天带来了什么小姐姐,呸,是带来了什么精彩的文章。
自从上次写了一篇面经之后,收获了很多支持我的粉丝。当然,在粉丝的强烈要求下,还想继续看小姐姐😍
当然,按照我的习惯,,肯定是给大家找到了很多的小姐姐,奈何技术不够,人家网站不让我用爬虫去抓,所以啊,这次只能放一些小姐姐了。
其实我的初衷是在大家阅读的同时也能身心愉悦,享受小姐姐带来的乐趣。奈何,,程序员闷骚男太多,都喜欢小姐姐,不喜欢文章。我就只有这样给大家奉上写好的文章,顺便插入一些小姐姐图。
话不多说,还是开始我们今天的主题。给我的同事妹妹讲一讲MyBatis运行原理。同事妹妹是同事是个妹妹,而不是我同事的妹妹,,别把我想的那么坏。😏

(深夜十二点,我正在激情的LOL中,突然一个电话响起)
妹妹:周哥周哥,你睡了吗?
我:啊,没呢,在看书
妹妹:我今天学习MyBatis源码的时候遇到点问题,你能帮帮我吗?
我:嗯…这么晚了,要不明天吧
妹妹:啊,,可是我今晚上就想弄清楚这个运行原理咋办
我:那行吧,你把电脑打开,我给你远程讲解吧
(远程了十分钟,终于因为网络原因,连不上而放弃了)
妹妹:周哥,你把你的住址发给我,我过来找你
我:这么晚了,不太好吧(快来,快来)
妹妹:诶呀,没事儿的,我都不怕,你怕什么,难道你会吃了我吗?
我:那怎么会,来吧,地址我发定位给你
(二十分钟后…咚咚咚)
我:来了
妹妹:(上身穿着T恤,下身穿着牛仔裤加拖鞋)周哥,实在不好意思,这么晚还来打扰你
我:没事儿,为了学习,可以理解(弟弟别闹)
妹妹:那我们就开始吧

老规矩,图片镇楼…
在这里插入图片描述

MyBatis的分层架构图

ps:这里参考了尚硅谷MyBatis课程的架构图

我:你说你想要了解MyBatis的源码,那先看看这个架构图吧
妹妹:好
在这里插入图片描述
妹妹:这个架构图说明了什么啊
我:我给你解释一下哈,其实,我们在看源码的时候,可以大概的把框架抽象成四层。从下到上,分别是引导层、框架支撑层、展示层以及接口层。每一层其实就是对应了我们的每一个步骤。我们想想写的第一个HelloWorld程序。

  //1.读取配置文件 
  InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
  //2.创建SqlSessionFactory的构建者对象 
  SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  //3.使用构建者创建工厂对象
  SqlSessionFactory factory = builder.build(in);
  //4.使用SqlSessionFactory生产SqlSession对象 
  SqlSession session = factory.openSession();
  //5.使用SqlSession创建dao接口的代理对象 
  UserDao userDao = session.getMapper(UserDao.class);
  //6.使用代理对象执行查询所有方法 
  User users = userDao.findUserById(1);
  System.out.println(users);
  //7.释放资源 
  session.close();
  in.close();

我:我们这样来看,第一行代码,其实是加载我们写的配置文件。官方也给我们说了,如果我们不喜欢使用XML配置文件的形式,也可以参考java代码的形式对吧。
妹妹:哦,对,这里我在官网看到过,我给你翻一翻。
在这里插入图片描述
我:嗯,对的,就是这里。那我们接着往上看,看框架支撑层。这儿为什么要称作框架支撑层呢,你知道吗?
妹妹:是不是这些图块里面写的东西就是支撑MyBatis这个框架的主体部分呀
我:(摸了摸她的头)你真聪明,大致就是这个意思。我们知道,其实这个框架最主要的还是去解析我们写好的mybatis-config.xml配置文件,然后从里面取出我们写的configuration标签里面的所有内容,包括我们的事务管理这些。
我:那你看上面的两层,你大概能猜出来意思吗?
妹妹:嗯,我猜一下,这上面的这些东西是不是就是用来执行我们SQL的主体部分啊
我:对的。我们再去解析完这个配置文件之后,会去加载一个叫做Executor的类,然后这个类作为我们的执行器,然后从Configuration类中取出我们的SQL语句,这个语句就是我们写的mapper.xml文件中的语句,将这些语句执行完成之后,放在ResultSetHandler中去处理。ResultSet你熟悉吗?
妹妹:哦,这个我熟悉,就是jdbc里面的那个吗?
我:嗯,对的。待会儿我们看看源码,其实会发现,他底层就是用的jdbc里面的方法。
妹妹:好的。那也就是说,最后我们的结果集,其实还是类似于jdbc的做法吗?
我:对的。那你再猜猜,MyBatis是怎么让我们写的Mapper接口还能执行我们写的SQL语句呢?
妹妹:(想了5秒钟)是不是代理呀。
我:对的,就是代理模式。其实在MyBatis底层中,会有一个Map用来装我们的mapper,然后给我们的mapper生成一个代理对象,用代理对象去执行我们的方法。
我:其实,我们要执行语句,并不一定非要写mapper.xml文件,还可以去实现我们的接口来完成查询。所以,MyBatis这里就使用了代理模式。
妹妹:哦,我大概懂了。
我:你知道MyBatis中的拦截器吗?
妹妹:这个我知道,MyBatis的分页插件就是用的拦截器做的。
我:对,待会儿我们去看源码的时候,就能看到里面其实还用了一个责任链模式,来对我们的执行条件进行增强,给我们的Executor中添加拦截器。
妹妹:哇哦,周哥你好厉害。
我:(摸了摸自己头发)😁嘿嘿,哪儿有,这些都是比较基础的东西。那我们先看看源码吧。

ps:为了大家调试方便,最好还是跟着我一起来点一点源码,写写注释什么的(注释需要大家单独下载源码包,github上有,我这儿就不发了)。给大家准备了一份mybatis-helloworld的程序,就是入门级的那种,很简单。
在这里插入图片描述
可以直接下载,0积分,SQL文件也在里面。
点我下载mybatis-helloworld

SqlSessionFactory初始化过程

我:刚才给你讲的那些都听懂了吧
妹妹:嗯,听懂了。
我:那我们就开始讲源码了哦。再讲源码之前,你得答应我一件事
妹妹:什么啊
我:讲完了之后,你作为报答,你得亲我一下
妹妹:啊…那好吧,不过呢,你得讲懂了才行,不然的话,我就报警说你调戏良家妇女
我:那必须的(嘿嘿)

我:首先,我们得先看看第一个比较重要的东西,叫做SqlSessionFactory。这个听名字就知道,这个肯定是生产SqlSession的,那怎么来生产的呢?
我:来看看这行代码

InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder().build(in);

妹妹:这里,看名字,是不是像用的建造者模式。
我:嗯,对的,这里我们猜一下,其实里面就是用的一个内部类去实现的一个建造者模式,然后来构造我们的SqlSession。我们先点进去源码看看他的build()方法。
在这里插入图片描述
我:其实这里很简单啊,他最终其实是调用了有三个参数的方法,然后去new了一个XML配置文件的解析器用来解析我们的mybatis-config.xml文件,解析完成之后,最终是返回了一个DefaultSqlSessionFactory对象。
妹妹:嗯,这里我知道,那在build(parser.parse())这行代码又做了什么呢?
我:这里也正是我们要讲的,我们点进去看看。
在这里插入图片描述

我:看到了吗,其实这个方法,最主要的还是解析我们的mybatis-config.xml文件。在parse()方法中,是调用了一个parseConfiguration()方法,你看到那个 /configuration 像什么,知道吗?
妹妹:哦,这个我知道,就是我们写的那个最外层的 <configuration> 标签是吧。
在这里插入图片描述
我:对,我们再看看他调的那个parseConfiguration()方法。
在这里插入图片描述
我:看到这些解析节点的方法熟悉吗?
妹妹:哦,我懂了,就是在这里去解析的我们写的那一大堆节点对吧。
我:对的,你看吧,我们写的每一个配置文件中的节点属性都会在这里进行解析。我们再看看最下面的那一排mapperElement()方法,这儿,其实就是解析我们的<mappers>节点,我们再点进去看看。
在这里插入图片描述
我:这儿主要是看我红框框里面的部分。我们分析一下流程。在最上面有个if判断,会去判断我们的<mapper>节点是不是为空,当然,写的肯定不会为空,如果为空就直接报错了。然后又会走下一个if判断。其实这儿的判断主要就是去看你的<mappers>中的<mapper>中的属性是不是写的package,当然,我们个人习惯其实都是写resource标签对吧。所以我这儿就不去分析上面的判断,其实和下面相比也就是少了几个流程而已。
我:我们看一下代码,其实这里就还是分析我们写的resource属性中的mapper.xml文件,然后我们再去看看mapperParser.parse()方法;
在这里插入图片描述
ps:这个地方注意我蓝色框框中的代码,我先不分析,留个坑,等会儿回来看。
我:你看我红色框框中标注的方法,猜一下,像不像是去解析我们写的mapper.xml中的节点属性,调用的一个方法。
我:我们接着再往下点,看看解析我们的mapper文件是怎么去解析的。
在这里插入图片描述
我:你看这儿,像不像是我们写的增删查改的方法标签。
妹妹:哦,我猜一下,这里是不是去解析那些方法标签啊,就是这个。
在这里插入图片描述
我:对的,你真聪明,其实就是解析我们的这些标签。
我:然后我们继续看看他的方法是干了些什么。
在这里插入图片描述
妹妹:哦,到这里,其实就是去解析我们的那些<select>标签了是吧。
我:对的,我们继续往下看。
在这里插入图片描述
我:我们点进去这个方法之后,会发现,他是将我们写的所有属性全都放在了一个叫做MappedStatement的东西去装的。
妹妹:这个MappedStatement又是干嘛的啊。
我:这里啊,这里其实就是引出来了一个大东西,我们点进去方法看看。
在这里插入图片描述
我:其实走到这儿,我们就能大概猜出来了,我们所有的东西,都是在一个叫做Configuration类中放着的。而且,一个MappedStatement就是一个增删改查标签。我们写的标签中的所有东西其实都在这里面存着的。
妹妹:我打个断点看看
在这里插入图片描述
妹妹:哇,真的欸,这么神奇的吗
我:其实,到这里,我们前面看的那个mapper的解析就已经解析完成了,我们的所有信息都放在configuration中。再回到之前的那个地方,解析/configuration的地方。(小伙伴别觉得晕哦)
在这里插入图片描述
我:到这里,configuration中就已经保存了我们所有的信息了。
妹妹:哇,你真棒。这么复杂你都理清楚了。
我:欸,这些都是小意思。其实啊,这里我们得去注意debug中的一个很重要的属性
在这里插入图片描述
我:看见了吗,这里维护了一个HashMap,里面的key存的是我们的UserDao接口,value存的是我们的代理工厂。还记得我们上面有个蓝色的框框吗,那里我是不是说了有个坑,其实就是在这里去解决的。
我:先看看这个mapperRegistery是什么
在这里插入图片描述
我:是不是很奇怪,这里居然有一个HashMap,而且这个map中的k和v就是保存的我们debug中的那些属性。但是这里面的值是哪儿来的呢?
妹妹:不知道,,你给我讲一下嘛。
我:还记得前面有个蓝色框框的代码在哪儿吗?其实就是解析我们mybatis-config.xml中<mappers>节点中的mapper.xml文件。我们看看那儿的代码是怎么走的。
在这里插入图片描述
我:看这儿,熟悉吗?
妹妹:嗯,这个是反射吗?
我:对的,他会去利用我们写的resource属性里面的路径去反射我们的类,然后生成一个代理对象。再放进去我们的configuration中。
妹妹:那这儿就是会加到那个map中去吗?
我:嘿嘿,我不告诉你,我们接着往下看。
在这里插入图片描述
在这里插入图片描述
我:其实在这儿,就是我们的map中的属性进行赋值。所以啊,我们debug出来的结果,就是在这儿进行赋值的。
妹妹:哦,原来是这样啊。难怪,我一直都没看到这个mapper是怎么去生成出来的。
我:这下你搞明白了吧。所以啊,这个就是我们build()方法走的全部流程。
妹妹:那我刚才看到他build()方法执行完了之后返回了一个new DefaultSqlSessionFactory(config)。
我:嗯,你记性可以啊。我们看看。
在这里插入图片描述
我:其实啊,这个DefaultSqlSessionFactory还是去实现了SqlSessionFactory接口。所以,我们写的代码里面的SqlSessionFactory就是这么来的。
妹妹:哇,周哥你真厉害。这么绕你都给我讲明白了。
我:嘿嘿,小问题嘛,你要记得你刚才答应的哦。
妹妹:😳我答应了什么啊。
我:亲我啊
妹妹:哎呀,你坏死了。我先去上个厕所哈,周哥,你先去喝口水,我们再接着往下讲
我:好,去吧(弟弟别闹)

ps:至此,第一个build()方法就讲解完毕,看到这里的小伙伴也可以好好的理一下流程。我们马上就继续往下讲。分析清楚这个到底是怎么执行的。在这里也奉上妹妹的一张生活照。
在这里插入图片描述

openSession()方法获取SqlSession()对象

在上面的方法中,我们已经获取到了SqlSessionFactory,里面存放了我们的MappedStatement。经过debug我们发现,其实在第一行代码中,他最主要的就是去解析我们的mybatis-config.xml文件,然后通过解析的标签里面去找到他的mapper文件,再去将我们mapper文件中写的namespace的路径通过反射去加载到一个hashMap中进行存储,然后再去解析我们的sql语句,最后放在我们的MappedStatement中去。
那么下面的这个方法,其实最主要的还是通过我们上面拿到的SqlSessionFactory去获取到我们的SqlSession,通过这个SqlSession去执行我们的sql语句。
废话还是不多说了,我们继续。
ps:顺便提一句,如果是完整的看完了这个,那么后面这个结局肯定是会翻转的,各位lsp就别藏着了,乖乖看完。

妹妹:周哥,那下面这个SqlSession session = factory.openSession();又是干嘛的啊。
我:来,坐我旁边,我们接着看。
我:点进去源码我们看看,到底是做了个什么事情。
在这里插入图片描述
在这里插入图片描述
我:其实从这儿,可以简单的看出来一些东西。上面的方法最终是走到了这里,调用了openSessionFromDataSource()方法。里面传入了三个参数

ExecutorType:执行器类型  
TransactionIsolationLevel:事务的隔离级别
autoCommit:是否自动提交

我:那么这三个参数的值是什么呢?我们来debug跑一下看看。
在这里插入图片描述
我:其实我们去看看MyBatis的官方文档,使用的默认执行器就是SIMPLE
妹妹:哦,我看到这个四大对象的一个,是Executor
我:对的,其实在这里,他就会将我们上面获取到的configuration去new一个Executor执行器,然后将我们的事务信息,以及是否自动提交给放进去。
妹妹:那他这个newExecutor()方法是怎么执行的?
我:嗯,那我们点进去看看。
在这里插入图片描述

我:这儿,就是去判断我们的类型,因为我们之前传入的是SIMPLE类型,所以会走else里面的代码块。并且,会去判断一下我们有没有使用缓存。
我:我们再去看一下这里的缓存,到底是怎么去做的。
在这里插入图片描述
我:他这个地方的大概意思其实就是,将我们的执行器用缓存去包装一层。那么在后面进行查询的时候,就可以直接去调这里的查询,而不是去一次性跑整个逻辑了。就比如这里:
在这里插入图片描述
妹妹:哦,我懂了,其实这里就类似于我们的那个一级缓存是吧。
我:嗯,对的。我们再接着往下看。看一下缓存执行完了之后又做了什么?
在这里插入图片描述
我:在这个地方,他又调用了一个方法,叫做拦截器链。你知道这个方法是干嘛的吗?
妹妹:不知道,是干嘛的呀
我:其实在这一步就已经非常重要了。我们知道,MyBatis中可以自己写插件,插件的原理其实就是拦截器对吧。那么在这个地方,他就会将我么写的拦截器去放在我们的executor中去包装一层。我们去看看这个方法。
在这里插入图片描述
我:看见没,这里就会调用拦截器的方法,去将我们写的拦截器和Executor进行一次组装。这里其实也就是我们后面要用的分页插件的原理。
妹妹:哦,我懂了。分页其实就是写了个拦截器,然后放在这里,会去拦截到我们的executor,因为executor中有我们的那些sql信息,所以这里的拦截器就会去拦截我们的sql然后进行重写是吧
我:嗯,对的。真聪明
妹妹:😳哎呀,你别夸我了,继续往下讲。
我:好。那这里的Executor封装了一层拦截器之后,就会开始做返回。继续debug看看下面的流程。
在这里插入图片描述
我:到这里,基本上获取SqlSession的流程就走完了。我们大概想一下这块做了什么事情。
妹妹:我来说。这一块呢,就是会去根据我们上面获取到的Configutarion,从里面取出我们的当前环境,以及事务,执行器类型,再去对这些进行一次封装成一个Executor。再然后呢,给这个Executor中去把我们写的拦截器也给放进去,用的是一个拦截器链。最后,再进行返回,那么返回回来的这个Executor里面就存放了我们的拦截器以及执行器类型,事务控制这些。再把这个executor和configuration放在我们的SqlSession中,这样,就能拿到全部的信息了,我说的对吗?
我:嗯,还不错,你还是听懂了。那我们接着往下继续分析?
妹妹:好,来吧。
我:哦(😍)
妹妹:你在想啥呢?不正经,快继续讲
我:嘿嘿,逗一逗你嘛。

ps:到这里,我们获取SqlSession就已经分析完了,总结呢,也在妹妹说的话里面,如果有哪儿不清楚的,就在下方留言,我看到了会一一回复的。悄咪咪的告诉你们,刚才妹妹又发了几张生活照给我,我给你们看看。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

getMapper()运行原理解析

妹妹:那下面这一行getMapper()又是怎么执行的呢?
我:我们在最开始的时候是不是说过,MyBatis是用了一个代理类来帮我们的接口做的一个动态代理。那么,这儿的执行其实就是通过我们mapper的名字,去那个map中拿到我们生成出来的动态代理类。我们往下看看
在这里插入图片描述
在这里插入图片描述
我:其实在这里我们可以看到,他传了两个参数进去,一个是我们的mapper接口,另一个就是我们的SqlSession。在刚才的时候我们说过,这个SqlSession里面维护了一个configuration和Executor。那也就是说,此时在这一步,是有我们的全部配置信息的。自然而然,在maps中就能拿到我们放进去的动态代理类。
在这里插入图片描述
我:它将我们的SqlSession传进去了newInstance()方法,在这里,就是调用了JDK动态代理的代理对象,创建了一个代理类再进行返回。
我:所以在最后进行返回的是一个mapper的代理对象。我们根据多态的原则,可以使用接口去进行接收。
妹妹:哦,其实这个地方拿到的就是反射生成出来的代理类对吧。
我:嗯,对的。所以,这个地方还是比较重要的。
妹妹:那下面那个查询方法又是怎么去执行的呢?
我:那个查询方法,其实就是整个MyBatis的结尾了。我们待会儿就能看到,他其实还是用的jdbc的调用。
妹妹:那我们继续往下看吧
我:好,那我就继续了哦,这一块分析的时候有点绕,你要是觉得难受就说停(呸,我不是这个意思,别想偏)。

MyBatis执行查询的真正流程分析

我:我们先打个断点,看看会怎么去执行。
在这里插入图片描述
我:我们知道,既然是代理类,那么肯定是会执行invoke()方法的。在第一行这个Object.class.equals()是什么意思你知道吗?
妹妹:嗯,不知道。
我:你看他的参数,其实就是比较我们的这个方法所在的类是不是一个Object类,因为有些方法是toString()方法对吧(所有的类都默认继承了Object),所以在这里会进行一个判断,但是我们这儿执行的是自己写的接口类,所以这里并不会去执行。
我:他会去执行下面的一行代码,就是将我们的method包装成一个MyBatis认识的MapperMethod
在这里插入图片描述
我:然后,继续调用execute()方法,传入了两个参数,分别是sqlSession和args。我们知道,sqlSession里面放了我们所有的信息,args呢,其实就是我们方法中的参数值(我传的是1)
在这里插入图片描述
我:然后我们继续往下看看执行流程。
在这里插入图片描述
我:其中,会去获取到我们当前执行的命令类型,因为我们是select,那么会走下面的case SELECT。然后在里面的if判断,就会去看我们当前返回的是什么类型。因为我们返回的是一个实体类。所以会进入到我们的else语句里面去继续执行。
我:进入到else里面之后,我们再看看在这里插入图片描述
我:第一行就是将我们的参数转成sql语句中的参数。不妨可以进去看看。
在这里插入图片描述
我:点进去之后会发现还执行了一个getNamedParams()方法,来到这里,就会去判断我们的args是一个还是多个,将参数进行一个封装再返回。
我:我们回到之前那里,看看将参数封装好之后返回的是什么?

result = sqlSession.selectOne(this.command.getName(), param)

在这里插入图片描述

我:它继续调用了这一行代码传入了当前的方法的名字和封装好的参数,我们继续往下看。
在这里插入图片描述
我:在selectOne()方法中,其实还是调用了selectList()方法,无非就是可以做一个复用。如果结果只有一个,那么就拿到list中的第一个值就是我们要的结果,我们再点进去看看这个执行方法是怎么执行的
在这里插入图片描述
我:我们值卡说过,每一个MappedStatement里面装了我们每一个sql执行的详细信息。
在这里插入图片描述
我:在这里拿到信息之后,再去调用了一个
var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
方法,我们再点进去看看。
在这里插入图片描述
我:在这里去拿到一个BoundSql对象,里面就存放了我们所有的信息。
在这里插入图片描述
我:然后往下,去执行我们的缓存查询。
在这里插入图片描述
我:然后再往下继续执行query()方法
在这里插入图片描述
我:他会先去判断我们有没有开启缓存,这里的缓存其实是一个二级缓存,我们并没有开启。所以会走return 语句

return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

继续往下执行query()方法
在这里插入图片描述
我:这儿的代码有点长,我们慢慢来分析。
我:这代码的意思大概就是,他会先去检查我们的二级缓存中是否有值,如果没有值的话,它会继续往下执行
在这里插入图片描述
我:其实所以在这里,最终还是调用了一个queryFromDatabase()方法。我们点进去这个方法看一下
在这里插入图片描述
我:在这儿,去给本地缓存放一个key,那个key就是我们上面的那一大串值。然后去调用一个doQuery()方法,调用完成之后,将本地缓存中的key移除掉,然后又把key存进去,这次存的值就是我们查询的结果。我们继续点进去doQuery()看看执行结果
在这里插入图片描述
我:看第一行,其实底层还是使用的是原生jdbc,然后这儿又出现了一个新的东西,四大对象之一,StatementHandler
妹妹:好晕啊,这么绕
我:别急,马上就快结束了。我们接着往下看
我:这个StatementHandler就能创建除Statement对象,这个Statement对象就是我们原生jdbc中的东西。看见了prepareStatement()吗,熟悉吗?
妹妹:这个我知道,以前jdbc学过。
我:我们来看一下这个StatementHandler是怎么创建的。
在这里插入图片描述
在这里插入图片描述
我:其实在我们的<select>标签中,是可以有一个statement属性的在这里插入图片描述
我:这个地方其实就是去判断我们这儿写的是什么属性。默认其实就是PREPARED,在官网中也有说明。
在这里插入图片描述
在这里插入图片描述
我:在这里创建完成之后,用了拦截器将我们的statementHandler进行一次封装。
ps:这里创建的PrepareStatement详细的预编译不在此次分析目标中,有兴趣的朋友可以自行去看看。
我:然后我们回到之前的地方。
在这里插入图片描述
我:然后我们继续点进去query()方法。
在这里插入图片描述
我:然后其实到这里就已经执行完了。底层逻辑还是封装的jdbc的c查询方法。
ps:它下面的执行逻辑还是继续用的ResultSetHandler去将结果集进行一次封装,我这儿就不详细说了,不然的越来越绕。
妹妹:啊,太绕了,我感觉它这个底层逻辑都是一层套一层的执行啊。
我:对啊,MyBatis的强大之处就是在这里。

个人分享与源码总结

源码暂时就先分析到这里,我们在阅读源码的过程中,一步一步的引出来了MyBatis的四大对象。
在第一次阅读源码的时候,我个人建议是先debug通读一遍,然后去下载官方源码,在分析的过程中慢慢的写好注释,一步一步的循序渐进。
当然,如果你能找到一个好妹妹听你讲的话,那自然是更好,如果找不到的话,不妨去参考一下小黄鸭调试法(自行百度)。

总结:
mybatis运行原理:

  1. 通过加载mybatis全局配置文件以及mapper映射文件初始化configuration对象
    和Executor对象(通过全局配置文件中的defaultExecutorType初始化);
  2. 创建一个defaultSqlSession对象,将configuration对象和Executor对象注入给
    defaulSqlSession对象中;
  3. defaulSqlSession通过getMapper()获取mapper接口的代理对象mapperProxy
    (mapperProxy中包含defaultSQLSession对象)
  4. 执行增删改查:
    1)通过defaulSqlSession中的属性Executor创建statementHandler对象;
    2)创建statementHandler对象的同时也创建parameterHandler和 resultSetHandler;
    3) 通过parameterHandler设置预编译参数及参数值;
    4)调用statementHandler执行增删改查;
    5)通过resultsetHandler封装查询结果

故事番外

ps:还记得我上面说的吗,故事会进行一个反转。嘿嘿,来了哦。


妹妹:讲了一个半小时,终于讲完了呀,好累(伸个懒腰)
我:(瞟了一眼,吞口水)嗯,我的嘴巴也讲干了,我去喝个水
(5秒钟过后)
妹妹:giegie,要是你的女朋友知道这么晚我们俩在一个房间,还这么费力的给我讲题,她不会生气吧。
我:我的好妹妹,我没有女朋友。
妹妹:啊,那要不(😚)
我:你还记得最开始答应我的吗?
妹妹:啊,我答应了你什么
我:好啊,你不认账。
妹妹:哪儿有。你把眼睛闭上
我:(mua)
妹妹:哼,这个就算是给你今晚上给我讲题的报答了。
我:嗯,这么晚了,要不我送你回去吧。
妹妹:好啊(起身),哎呀,我钥匙好像忘带了,这个点了,开锁师傅估计也不会接电话了吧
我:那怎么办
妹妹:要不我在沙发将就一晚上吧
我:那怎么行,我睡沙发,你去睡床。
妹妹:可是…
我:别可是了,去睡吧,这么晚了。还好明天周六,不上班。
妹妹:好吧,那我先去睡了哦。
(半夜三点钟,沙发上多了一个人,一看,是妹妹来了)
我:嗯,你干嘛,这么晚了
妹妹:别说话,吻我。




(苍茫的天涯是我的爱,绵绵的青山脚下花正开)
我:wk,八点了。(睁眼一看,哪里有妹妹)tmd,做了个梦啊。

ps:别急,没这么快就结束的。
(地铁十分钟,到公司了)
我:啊,终于下班了(伸个懒腰)。
妹妹:周哥,今晚上你有事吗?
我:嗯,没啥事儿啊,咋了。
妹妹:那个,反正明天是周六,今晚上我来找你,你能帮我讲一下MyBatis源码吗?
我:(wk)啊,没问题,行




(未完待续)

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 22:41:08  更:2021-07-30 22:41:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 1:44:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码