Mybatis架构原理

架构设计

image.png

我们把Mybatis的功能架构分为三层:
(1) API接口层:提供给外部使用的接口 API,开发人员通过这些本地API来操纵数据库。接口层一接收到
调用请求就会调用数据处理层来完成具体的数据处理。
MyBatis和数据库的交互有两种方式:
a. 使用传统的MyBati s提供的API ;
b. 使用Mapper代理的方式
(2) 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根
据调用的请求完成一次数据库操作。
(3) 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是
共 用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑

主要构件及其相互关系

image.png

image.png

image.png

总体流程

(1) 加载配置并初始化

触发条件:加载配置文件
配置来源于两个地方,一个是配置文件(主配置文件conf.xml,mapper文件*.xml),—个是java代码中的 注
解,将主配置文件内容解析封装到Configuration,将sql的配置信息加载成为一个mappedstatement 对
象,存储在内存之中

(2) 接收调用请求

触发条件:调用Mybatis提供的API
传入参数:为SQL的ID和传入参数对象
处理过程:将请求传递给下层的请求处理层进行处理。

(3) 处理操作请求

触发条件:API接口层传递请求过来
传入参数:为SQL的ID和传入参数对象
处理过程:

(A) 根据SQL的ID查找对应的MappedStatement对象。
(B) 根据传入参数对象解析MappedStatement对象,得到最终要执行的SQL和执行传入参数。
© 获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
(D) 根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果。
(E) 释放连接资源。

(4) 返回处理结果

将最终的处理结果返回。

Mybatis源码剖析

传统方式源码剖析:

源码剖析-初始化

image.png

进入源码分析:

image.png

MyBatis在初始化的时候,会将MyBatis的配置信息全部加载到内存中,使用
org.apache.ibatis.session.Configuratio n 实例来维护
下面进入对配置文件解析部分:
首先对Configuration对象进行介绍:

image.png

image.png

image.png

介绍一下 MappedStatement :
作用:MappedStatement与Mapper配置文件中的一个select/update/insert/delete节点相对应。
mapper中配置的标签都被封装到了此对象中,主要用途是描述一条SQL语句。
初始化过程:回顾刚开 始介绍的加载配置文件的过程中,会对mybatis-config.xm l中的各个标签都进行
解析,其中有mappers 标签用来引入mapper.xml文件或者配置mapper接口的目录。

image.png

样的一个select标签会在初始化配置文件时被解析封装成一个MappedStatement对象,然后存储在
Configuration对象的mappedStatements属性中,mappedStatements 是一个HashMap,存储时key
=全限定类名+方法名,value =对应的MappedStatement对象。
•在configuration中对应的属性为

image.png

在 XMLConfigBuilder 中的处理:

image.png

到此对xml配置文件的解析就结束了,回到步骤2.中调用的重载build方法

image.png

源码剖析-执行SQL流程

先简单介绍SqlSession :
SqlSession是一个接口,它有两个实现类:DefaultSqlSession (默认)和
SqlSessionManager (弃用,不做介绍)
SqlSession是MyBatis中用于和数据库交互的顶层类,通常将它与ThreadLocal绑定,一个会话使用一 个
SqlSession,并且在使用完毕后需要close

image.png

SqlSession中的两个最重要的参数,configuration与初始化时的相同,Executor为执行器
Executor
Executor也是一个接口,他有三个常用的实现类:
BatchExecutor (重用语句并执行批量更新)
ReuseExecutor (重用预处理语句 prepared statements)
SimpleExecutor (普通的执行器,默认)
继续分析,初始化完毕后,我们就要执行SQL 了

image.png

获得 sqlSession

image.png

image.png

执行 sqlsession 中的 api

image.png

源码剖析-executor

继续源码中的步骤,进入executor.query()

image.png

image.png

image.png

image.png

image.png

上述的Executor.query()方法几经转折,最后会创建一个StatementHandler对象,然后将必要的参数传递给StatementHandler,使用StatementHandler来完成对数据库的查询,最终返回List结果集。
从上面的代码中我们可以看出,Executor的功能和作用是:

(1、根据传递的参数,完成SQL语句的动态解析,生成BoundSql对象,供StatementHandler使用;
(2、为查询创建缓存,以提高性能
(3、创建JDBC的Statement连接对象,传递给StatementHandler对象,返回List查询结果。

源码剖析-StatementHandler

StatementHandler对象主要完成两个工作:

对于JDBC的PreparedStatement类型的对象,创建的过程中,我们使用的是SQL语句字符串会包含若干个?占位符,我们其后再对占位符进行设值。StatementHandler通parameterize(statement)方法对 S tatement 进行设值;

StatementHandler 通过 List query(Statement statement, ResultHandler resultHandler)方法来完成执行Statement,和将Statement对象返回的resultSet封装成List;

进入到 StatementHandler 的 parameterize(statement)方法的实现:

image.png

image.png

image.png

从上述的代码可以看到,StatementHandler的parameterize(Statement)方法调用了
ParameterHandler的setParameters(statement)方法,
ParameterHandler的setParameters(Statement )方法负责根据我们输入的参数,对statement对象的 ?
占位符处进行赋值。
进入到StatementHandler 的 List query(Statement statement, ResultHandler resultHandler)方法的实现:

image.png

从上述代码我们可以看出,StatementHandler 的List query(Statement statement, ResultHandler
resultHandler)方法的实现,是调用了 ResultSetHandler 的 handleResultSets(Statement)方法。

ResultSetHandler 的 handleResultSets(Statement)方法会将 Statement 语句执行后生成的 resultSet结 果集转换成List结果集

image.png

image.png

Mapper代理方式:

回顾下写法:

image.png

思考一个问题,通常的Mapper接口我们都没有实现的方法却可以使用,是为什么呢?答案很简单动态代理

开始之前介绍一下MyBatis初始化时对接口的处理:MapperRegistry是Configuration中的一个属性,它内部维护一个HashMap用于存放mapper接口的工厂类,每个接口对应一个工厂类。mappers中可以配置接口的包路径,或者某个具体的接口类。

image.png

当解析mappers标签时,它会判断解析到的是mapper配置文件时,会再将对应配置文件中的增删 改查标签 封装成MappedStatement对象,存入mappedStatements中。(上文介绍了)当
判断解析到接口时,会建此接口对应的MapperProxyFactory对象,存入HashMap中,key =接口的字节码对象,value =此接口对应的MapperProxyFactory对象。

源码剖析-getmapper()

进入 sqlSession.getMapper(UserMapper.class )中

image.png

image.png

源码剖析-invoke()

在动态代理返回了示例后,我们就可以直接调用mapper类中的方法了,但代理对象调用方法,执行是在MapperProxy中的invoke方法中

image.png

进入execute方法:

image.png

image.png

image.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一生酷到底

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值