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.mzph.cn/news/537124.shtml

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

相关文章

Mybatis源码之与Spring集成包

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

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 …

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-…

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

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

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…

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

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

Maven高级之插件开发

前言 终于来到了Maven的插件开发&#xff0c;其实Maven的插件并没有想象的那么难&#xff0c;刚开始讲Maven基础的时候就演示了一下JDK是如何打包的&#xff0c;Maven打包只是在JDK打包上封装了一层而已&#xff0c;Maven也支持自定义插件开发 创建 我们先使用quickstart原型…

Maven高级之archetype(原型/骨架)开发

前言 archetype这个的主要功能就是将写好的项目模块打包成一个原型&#xff0c;然后提供给其他人使用&#xff0c;这样别人就可以快速使用这个项目模板了。 这个东西虽然很多人都基本用不上&#xff0c;但原型这个东西用的好还是很方便的&#xff0c;能够在开发新项目上省去大…

深度学习在搜索业务中的探索与实践

本文根据美团高级技术专家翟艺涛在2018 QCon全球软件开发大会上的演讲内容整理而成&#xff0c;内容有修改。引言 2018年12月31日&#xff0c;美团酒店单日入住间夜突破200万&#xff0c;再次创下行业的新纪录&#xff0c;而酒店搜索在其中起到了非常重要的作用。本文会首先介绍…

SpringBoot自动配置原理流程

前言 新公司太忙了&#xff0c;都没啥空更新博客&#xff0c;就随便记录一下以前的学习笔记吧。SpringBoot是基于Spring上的衍生框架&#xff0c;只要看懂了Spring的话&#xff0c;学这个就比较简单了&#xff1b;SpringBoot也是在当前微服务时代下流行的框架&#xff0c;并且…

SpringBoot自定义Starter(自动配置类)

前言 SpringBoot其实从诞生以来围绕的核心就是快速构建项目&#xff0c;快速构建的前提是有人帮你做好轮子&#xff0c;开发者只要拿来即用就好了&#xff0c;而造好轮子的人就是SpringBoot的开发者&#xff0c;引入自动配置的形式帮助开发者快速创建项目&#xff0c;而自动配…

Java并发编程之synchronized关键字解析

前言 公司加班太狠了&#xff0c;都没啥时间充电&#xff0c;这周终于结束了。这次整理了Java并发编程里面的synchronized关键字&#xff0c;又称为隐式锁&#xff0c;与JUC包中的Lock显示锁相对应&#xff1b;这个关键字从Java诞生开始就有&#xff0c;称之为重量级锁&#xf…

通过代理模式 + 责任链模式实现对目标执行方法拦截和增强功能

前言 最近需要实现一个插件功能&#xff0c;但是如果做成两个接口的话&#xff08;即执行前和执行后&#xff09;&#xff0c;那么会降低插件的可玩性&#xff0c;所以需做成类似AOP的环绕通知形式&#xff0c;所以就使用到了责任链模式和代理模式进行实现。 介绍 代理模式(P…

vscode Go 1.11.4 编译错误 need Delve built by Go 1.11 or later

更新golang的版本为1.11.4之后vscode编译错误&#xff1a;executables built by Go 1.11 or later need Delve built by Go 1.11 or later 原因是delve的版本太老了&#xff0c;需要更新&#xff0c;且delve的github地址已经更换&#xff0c;很多教程里的地址是不对的 新地址安…

Navicat使用教程:使用Navicat Query Analyzer优化查询性能(第1部分)

下载Navicat Monitor最新版本Navicat Monitor 是一套安全、简单而且无代理的远程服务器监控工具。它具有强大的功能使你的监控发挥最大效用。受监控的服务器包括 MySQL、MariaDB 和 Percona Server&#xff0c;并与 Amazon RDS、Amazon Aurora、Oracle Cloud、Microsoft Azure …