Mybatis源码之核心流程分析

终于谈到了Mybatis最核心的东西了,最核心的就是通过配置XML文件或注解中的SQL,直接调用接口就能执行配置好的SQL语句并封装成对应的返回类型的数据。

先看一下Mybatis使用示例:

//创建Builder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//读取配置文件IO流
InputStream is = Resources.getResourceAsStream("mybatis/mybatis-cfg.xml");
//解析IO流到内存Configuration对象中
SqlSessionFactory build = builder.build(is);
//获取一个持久化会话对象
SqlSession openSession = build.openSession();
//通过SqlSession调用
List list = openSession.selectOne("com.test.mybatis.MybatisTest.official.dao.IUserDao.getUserInfo");
System.out.println("============"+list);
//通过接口对象调用
IUserDao dao = openSession.getMapper(IUserDao.class);
System.out.println(dao.getUserLimit());//关闭SqlSession
openSession.close();

虽然看起来使用非常简单,但是内部构建这么一个ORM框架还是很艰难的,所以本章节会特别长

设计模式

照旧先来看一看设计模式

建造者模式(Builder Pattern)

使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

UML:

Builder:给出一个抽象接口,以规范产品对 象的各个组成成分的建造。这个接口规定要实 现复杂对象的哪些部分的创建,并不涉及具体 的对象部件的创建;

ConcreteBuilder:实现Builder接口,针对 不同的商业逻辑,具体化复杂对象的各部分的 创建。 在建造过程完成后,提供产品的实例;

Director:调用具体建造者来创建复杂对象的 各个部分,在指导者中不涉及具体产品的信息, 只负责保证对象各部分完整创建或按某种顺序 创建;

Product:要创建的复杂对象。

建造者模式对齐工厂模式创建出来的对象要更加的复杂,适用于实例化对象频繁改变的场景,适合流式编程。

但是现在流式编程是趋势,所以使用建造者模式创建对象的框架会越来越多,下面会讲到流式编程。

策略模式(Strategy Pattern)

一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

应用最多的就是if else代码当中

UML:

 

Context:算法调用者,使用setStrategy方法灵活的选择策略(strategy);

Strategy:算法的统一接口;

ConcreteStrategy:算法的具体实现;

源码分析

构建并解析XML文件

在使用的过程中都了解到了,首先就是将Mybatis的配置XML文件进行解析,解析后的数据都是存于Configuration对象当中,

先看一下Configuration这个类,单例,生命周期是应用级别,属性太多这里就不全截图出来了,大家可以自己下载源码去查看,截图如下:

但是在这个类中有几个对象需先讲一下:

MapperRegistry

mapper接口动态代理工厂类的注册中心。在MyBatis中,通过mapperProxy实现 InvocationHandler接口,MapperProxyFactory用于生成动态代理的实例对象;

TypeAliasRegistry

所以别名存储的地方,但是大家可以去看一下Configuration的构造方法,各类的默认参数都已经设置进去,不仅仅是Configuration的构造,在它自己的构造中将jdk自带的一些类也加进去了,这就是为什么有些别名默认就有的原因:

这个类里面也是有个Map<String,Class<?>>的这样的map用来储存这些数据

mappedStatements

这个是所有SQL信息储存的地方,使用的事继承自HashMap的自定义类StrictMap,这个map的key值为mapper的XML的namespace加上select|update|delete|insert标签的ID。具体的下面会谈到。

SqlSource

mapper.xml文件中的sql语句会被解析成SqlSource对象,经过解析SqlSource包含的语 句最终仅仅包含?占位符,可以直接提交给数据库执行;

TypeHandlerRegistry

是将数据库中的类型转换成JDK中的类型,进行对应,这个也有默认的集合,大家也可以去源码里面看一下。

整体介绍

整体解析建造者Builder类关系图:

使用的建造者图解:

我们就跟着解析流程讲解一下(在创建XMLConfigBuiler对象的时候会把Configuration对象创建出来):

进XMLConfigBuilder对象的parse方法看,执行了一个parseConfiguration(parser.evalNode("/configuration"));解析对象之前封装的XNode节点数据;

有些并非很重要的方法就没有标明,所以感兴趣的可以去看一下。

解析properties标签

解析完后会将所有的数据设置在configuration对象当中。

解析typeAliases标签

解析plugin标签

插件的使用这好像好没有提到,等后面在说吧。

解析mappers标签

这个算是解析文件里的一个比较中的东西

这时候开始使用XMLMapperBuilder建造者开始建造数据了:

我们看一下configurationElement方法:

这里的最后一个方法就开始了XMLStatementBuilder建造者开始建造了,看一些比较关键的地方

在创建MappedStatement对象时,使用的是流式编程

将数据全部加载完后,就是绑定工作空间了

在绑定方法中,如果namespace不是指定的接口全类名,那么就不会被添加到 mapperRegistry对象当中,这个对象就是用来跟接口做绑定的,进入到mapperRegistry的addMapper方法当中,

基本就是这么将动态代理跟namespace绑定的,构造XML的过程基本完结了,使用Mybatis的初始化已经完成,接下来就是使用持久化会话SqlSession这一块了

创建SqlSession

SqlSession是Mybatis对外提供的一个重要接口,可以通过这个跟数据库进行交互,或者创建接口代理对象,

UML:

创建一个默认的SqlSession工厂,这里用到了抽象工厂设计模式,之前为博客中提到了抽象工厂,那么这里就不细讲了,

我们调用时创建出了一个默认的DefaultSqlSession对象,在之前的示例当中,我们可以直接调用selectList方法也能调用getMapper方法,其实直接使用SelectList方法是ibatis编程模型,当加入了getMapper方法后就是采用接口形式开发,这种开始模式比之前的ibatis开发模式要更为简洁,并清楚业务。

我们先看一下原始的ibatis编程,即调用namespace+id方法

我们在看一下getMapper编程模式:

创建除了动态代理类之后,我们看一下代理类的实现:

这里的代理有一定的版本问题,由于JDK8支持在接口中写方法主体,所以需做一层判断才能执行正确的方法。

又是在invoke中执行的是invoke方法,所以在PlainMethodInvoker这个对象,执行的是mapperMethod.execute,

所以由此看出,getMapper也是基于ibatis编程模式开发。

SqlSession基本讲完了,接下来就是Executor执行器了。

Executor执行器

这个用到是模板模式,我在AQS中谈到的设计模式也是模板设计模式,模板模式-设计模式

BaseExecutor:抽象类,实现了executor接口的大部 分方法,主要提供了缓存管理和事务管理的能力,其他 子类需要实现的抽象方法为:doUpdate,doQuery等方法;

这个有四个对应的实现类:

SimpleExecutor:默认配置,使用PrepareStatement对象访问数据库,每次访问都要创建新的 PrepareStatement对象;

ReuseExecutor:使用预编译PrepareStatement对象访问数据库,访问时,会重用缓存中的statement对象;

BatchExecutor:实现批量执行多条SQL语句的能力;

ClosedExecutor:异常执行器。

默认的方法为SimpleExecutor(在Configuration参数中有),之前看到是执行了Executor中的query方法,这里讲一下:

进入到queryFormDatabase方法中:

doQuery方法中,发现多了Executor也并非执行,让Handler去执行:

通过对SimpleExecutor doQuery()方法的解读发现,Executor是个指挥官,它在调度三个Handler工作:

StatementHandler:它的作用是使用数据库的Statement或PrepareStatement执行操作,启承上启下作用;

ParameterHandler:对预编译的SQL语句进行参数设置,SQL语句中的的占位符“?”都对应 BoundSql.parameterMappings集合中的一个元素,在该对象中记录了对应的参数名称以及该参数的相关属性

ResultSetHandler:对数据库返回的结果集(ResultSet)进行封装,返回用户指定的实体类型;

StatementHadnler

BaseStatementHandler:所有子类的抽象 父类,定义了初始化statement的操作顺序, 由子类实现具体的实例化不同的statement (模板模式);

RoutingStatementHandler:Excutor组件 真正实例化的子类,使用静态代理模式, 根据上下文决定创建哪个具体实体类;

SimpleStatmentHandler :使用statement 对象访问数据库,无须参数化;

PreparedStatmentHandler :使用预编译 PrepareStatement对象访问数据库;

CallableStatmentHandler :调用存储过程;

在获取到对应的Statement对象之后就是执行Statement并封装结果集

随着Executor执行器执行完毕,数据也就这样执行出来了。

Mybatis大部分的核心知识基本都在这里,但是难免还是会有一些遗漏;后面遇到了就会做一些补充。

很多插件以及可扩展的方法接口等等,Mybatis发展这么多年,不可能在一段时间内知晓,还需潜心学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/537124.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/537124.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mimakatz用法_两步完成利用procdump64+mimikatz获取win用户密码

使用procdump64mimikatz可实现从内存中获取明文密码工具链接&#xff1a;https://pan.baidu.com/s/1gNc9qLcNSNBohIVrAiqShw 密码&#xff1a;fc38首先得先获取到内存文件lsass.exe进程, 它用于本地安全和登陆策略,一般在进程管理器中能看到, 比如这样1.导出lsass.exeprocdump6…

ios app提交之前需要哪几个证书

1、遇到的问题 一款App在别人的机器上开发和发布&#xff0c;现在迭代更新和开发需要在一台新mac机上开发和发布。&#xff08;使用同一个开发者账号&#xff09;问题&#xff1a; 1.在新mac机器上开发并导入真机测试&#xff0c;是不是需要从别人的机器上面导处开发者证书、开…

Mybatis源码之与Spring集成包

这次讲讲Mybatis与Spring的整合&#xff0c;作为两款优秀的开源框架&#xff0c;被大众广泛使用&#xff0c;自然是需要强强联合的。 使用示例 先看一下怎么使用&#xff0c;首先需要引用这两款框架的jar包&#xff1a; <dependency>//spring-webmvc会自动去引入其他S…

hadoop主节点切换_hadoop2.0 HA的主备自动切换

在《hadoop2.0 QJM方式的HA的配置》一文中介绍了HA的配置&#xff0c;是通过手工进行主备切换的。本文在这基础上&#xff0c;继续介绍HA的主备自动切换(automatic failover)的配置。自动切换是通过配置zookeeper来实现的&#xff0c;关于zookeeper的安装和配置&#xff0c;在这…

Mybatis源码之插件模块分析

总结完这个Mybatis的整体主要功能基本上就差不多完&#xff0c;还有一些细节的部分&#xff0c;后续都会记录补充。 插件这个东西一般用的比较少&#xff0c;就算用的多的插件也算是PageHelper分页插件&#xff1b; PageHelper官网&#xff1a;https://github.com/pagehelper…

AMD推出7nm高端显卡Radeon VII,直指英伟达RTX 2080

显卡战争已经发展到了2019年&#xff0c;并且变得比任何人预想的都要激烈。 CES 2019大会上&#xff0c;AMD发布了第一款消费级的 7nm GPU&#xff0c;取名&#xff1a;Radeon VII。据了解&#xff0c;这不是 AMD 的第一颗 7nm 处理器&#xff08;早期以 AI 运算为主的 Radeon …

电子绘本pdf_【孩子必看的】20本世界著名英文绘本 | PDF电子版+MP3音频

原标题&#xff1a;【孩子必看的】20本世界著名英文绘本 | PDF电子版MP3音频2 —6岁年龄段的孩子&#xff0c;自我意识逐渐萌芽&#xff0c;已经明白书是一种“特殊”的玩具&#xff0c;不在撕书、咬书、把书搬来搬去。这个阶段他们记忆力超强&#xff0c;唐诗、三字经啥的&…

Spring集成Mybatis多数据源配置

既然在整理Mybatis那就把经常用的这个多数据源的笔记也整一下吧。 Spring集成Mybatis在之前就已经提到了。Spring集成Mybatis 集成Mybatis多数据源有两种方式&#xff1a; 1、创建多个SqlSessionFactory&#xff0c;扫描每个SqlSessionFactoryBean对应的包&#xff0c;形成了…

Spring文件上传

2019独角兽企业重金招聘Python工程师标准>>> Spring文件上传 1、所需依赖包&#xff1a;commons-fileupload-1.3.1.jar2、Maven配置文件pom.xml文件中加入依赖Jar包<dependency><groupId>commons-fileupload</groupId><artifactId>commons-…

中英离线翻译mac_Instant Translate for Mac-即时翻译Mac版下载 V1.3.0-PC6苹果网

即时翻译(Instant Translate)Mac版是一款Mac平台的翻译及辞典软件&#xff0c;Instant Translate支持90的语言互翻译&#xff0c;通过ControlS切换语言&#xff0c;并且支持发音功能&#xff0c;并且支持自动检测语言并进行翻译。软件特色Instant Translate的主要特点&#xff…

基于Zookeeper使用ZkClient实现分布式锁

有段时间没写博客了&#xff0c;在整理之前写过的一套自定义框架&#xff0c;并且整理好上传值github上了&#xff0c;也有一些新功能还在开发&#xff0c;欢迎大家使用&#xff1a;一个好用的Http接口请求工具组件 可能今天这篇文章跟之前的比有些跳跃性&#xff0c;一下子就…

算法题学到的一些小语言细节

1.要学会用i&#xff1b;可以简化很多代码&#xff1a;i&#xff1b;copyFromMe(i)&#xff1b;可以写成&#xff1a;copyFromeMe(i) 2.StringBuffer也跟列表一样有append函数&#xff1b; 3.if语句是分支不能进行循环&#xff0c;要写成while才能替代循环里面的判断 4. 这里的…

android 按钮带图标 阴影_android中带图标的按钮(ImageButton)怎么用

展开全部除了Android系统自带的Button按钮以外&#xff0c;还提供了带图标的按钮ImageButton要制作带图标的按钮&#xff0c;首先要在布局62616964757a686964616fe58685e5aeb931333337613163文件中定义ImageButton&#xff0c;然后通过setImageDrawable方法来设置要显示的图标。…

Zookeeper基础常用操作以及ACL权限

这次将Zookeeper的一些基础用法以及权限这块的都补充一下在这篇博客中。 上篇博客介绍了基于ZooKeeper实现的分布式锁&#xff0c;也介绍了一些ZooKeeper的节点类型以及监听机制&#xff0c;今天这里就不作过多的介绍了&#xff0c;大家也可以自行的去官方文档上看看更具体的介…

[中医经络学习一]足阳明胃经

人体有六脏&#xff08;心、肝、脾、肺、肾五脏&#xff0c;再加心包&#xff09;六腑&#xff08;胃、小肠、大肠、膀胱、胆、三焦&#xff09;&#xff0c;每个脏腑都联接着一条经络&#xff0c;一共12条经络&#xff0c;称“十二正经”&#xff0c;经络的走向在四肢两侧基本…

ThreadLocal原理解析以及是否需要调用remove方法

平常的开发过程中&#xff0c;如果有个类不是线程安全的&#xff0c;比如SimpleDateFormat&#xff0c;要使这个类在并发的过程中是线程安全的&#xff0c;那么可以将变量设置位局部变量&#xff0c;不过存在的问题就是频繁的创建对象&#xff0c;对性能和资源会有一定降低和消…

Maven基础及概念

前言 今天就来聊聊Maven的基础和一些比较概念性的东西&#xff0c;还有一些常用的Maven命令啥的&#xff0c;主要是某人脑子记不住&#xff0c;记在博客中让她自己看吧&#xff0c;省的费心给她找。 后续的文章会聊到Maven的一些比较高级用法&#xff0c;像自定义插件&#x…

织梦缩略图自动补齐绝对路径_织梦生成文章内容缩略图时自动加上域名绝对路径...

今天又接了个织梦CMS的有偿服务,客户想要后台添加文章内容的时候,缩略图自动变成带上绝对路径的格式.比如我们默认的缩略图是这样的 /uploads/allimg/150814/123P2NB-0-lp.png 他想要的效果是这样的 http://www.youwujun.com.cn/uploads/allimg/150814/123P2NB-0-lp.png大家懂我…

BUAA 436 孟竹的复习计划(二维树状数组)

题目链接&#xff1a;http://acm.buaa.edu.cn/problem/436/ 题意&#xff1a;一个数列两种操作&#xff1a;&#xff08;1&#xff09;将某个位置的数字改成另一个数字&#xff1b;&#xff08;2&#xff09;交换两个位置的数字。每次操作之后输出逆序数的个数。 思路&#xff…

Maven之pom.xml常用标签解析及镜像配置

前言 Maven仅仅是个打包工具而已&#xff0c;个人觉得没有太大必要花费在打包工具上&#xff0c;这里就列举一下个人觉得会常用标签的使用就好了&#xff0c;原理啥的基本就不太会去深度了解了&#xff0c;如果以后遇到需了解Maven工作原理的工作的话&#xff0c;到时候一定分…