思维导图手撕MyBatis源码

文章目录

  • 前置准备
  • 通过类加载器读取配置文件流
  • 创建sqlSessionFactory
    • 建造者模式的使用
  • 打开SqlSession
  • 获取Mapper接口对象
  • 执行Mapper接口方法

前置准备

既然要读MyBatis的源码,那么我们就要先弄清楚MyBatis的入口在哪。这里我们直接写一个标准的MyBatis使用程序,以此来寻找入口分析源码:

//第一步:读取mybatis-config.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

//第二步:构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

//第三步:打开SqlSession
SqlSession session = sqlSessionFactory.openSession();

//第四步:获取Mapper接口对象
UUserInfoMapper uUserInfoMapper = session.getMapper(UUserInfoMapper.class);

//第五步:调用Mapper接口对象的方法操作数据库;
UUserInfo uUserInfo = uUserInfoMapper.selectByPrimaryKey(1);

 //第六步:业务处理
log.info("查询结果: " + uUserInfo.getId() + "--" + uUserInfo.getPhone());

通过类加载器读取配置文件流

在这里插入图片描述

这个地方你替换成为这个也是可以的;

//第一步:读取mybatis-config.xml配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//InputStream inputStream = App.class.getClassLoader().getResourceAsStream("mybatis-config.xml");

或者

Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatisConfig.xml")

这个方法更加通用,在web环境和java环境下均可以使用

创建sqlSessionFactory

//第二步:构建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

这个地方使用了建造者模式。build方法返回的实际上是一个DefaultSqlSessionFactory对象(实现了SqlSessionFactory)并持有一个Configuration的引用:
在这里插入图片描述

在这里插入图片描述
完整过程如下:
在这里插入图片描述
总结:

千层饼读法:

第一层:

  • new SqlSessionFactoryBuilder().build(InputStream)创建了一个SqlSessionFactory对象

第二层:

  • 创建XMLConfigBuilder 对象:new XMLConfigBuilder(Reader reader, String environment, Properties props)
  • XMLConfigBuilder.parse():解析xml文件获得Configuration对象
  • new DefaultSqlSessionFactory(Configuration):new 了一个DefaultSqlSessionFactory传入了刚才解析出来的Configuration对象,然后返回这个SqlSessionFactory对象

第三层:解析new XMLConfigBuilder(Reader reader, String environment, Properties props)方法

  • new XMLMapperEntityResolver():创建了一个XML映射器实体解析器
  • new XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver):传入XML映射器实体解析器,构造出XPathParser
  • 通过XMLConfigBuilder(XPathParser parser, String environment, Properties props)构造器返回XMLConfigBuilder对象

解析:
XPathParser:XPathParser核心功能是封装了XPath,对表达式进行解析,并转化成为指定的数据类型,其属性如下;

    private Document document;
    private boolean validation;
    private EntityResolver entityResolver;
    private Properties variables;
    private XPath xpath;
  • document:要解析的xml文件被转化成的Document对象。
  • validation:获取document时是否要开启校验,开启校验的话会根据xml配置文件中定义的dtd文件校验xml格式,默认不开启校验。
  • entityResolver:实体解析器,用于从本地工程目录中引入dtd文件,而不是根据网络URL去加载校验文件。
  • variables:mybatis-config.xml配置文件中,节点引入或定义的属性。
  • xpath:封装的XPath对象,用来解析表达式。

所有构造函数做的事都如下所示:

    public XPathParser(InputStream inputStream, boolean validation, Properties variables) {
        commonConstructor(validation, variables, null);
        this.document = createDocument(new InputSource(inputStream));
    }
  • commonConstruct()方法初始化了除Document之外的其他类属性,XPath是通过XPathFactory创建的
  • createDocument用来初始化document
    在这里插入图片描述
    // 将InputSource对象转化为Document对象
    private Document createDocument(InputSource inputSource) {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(validation);   // 是否要校验由外界传入的值确定
            factory.setNamespaceAware(false);    // 如果要使用mybatis的XSD Schema,此处必须设为true,但源码里是false,说明官方默认用dtd来做校验,舍弃了XSD Schema
            factory.setIgnoringComments(true);   // 默认忽略注释
            factory.setIgnoringElementContentWhitespace(false);  // 只有开启校验才能去除xml中的空白节点,但是不知是否开启校验,所以这里设为了false
            factory.setCoalescing(false);
            factory.setExpandEntityReferences(true);    // 默认开启使用扩展实体引用
            
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setEntityResolver(entityResolver);  // 使用传入的EntityResolver对象
            builder.setErrorHandler(new ErrorHandler() {  // 定义解析xml文档的错误处理器,如果发生了错误或致命错误则直接抛出异常,如果是警告默认不做处理
                @Override
                public void error(SAXParseException exception) throws SAXException {
                    throw exception;
                }
                
                @Override
                public void fatalError(SAXParseException exception) throws SAXException {
                    throw exception;                    
                }               
                
                @Override
                public void warning(SAXParseException exception) throws SAXException {}
            });
            return builder.parse(inputSource);  //开始解析
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
  • 要解析一个xml文件为Document,需要DocumentBuilder类的支持,实际上DocumentBuilder本身就支持多种形式的xml的解析,这里之所以先统一转成InputSource,大概是为了代码简洁一点吧!
  • DocumentBuilder对象由DocumentBuilderFactory创建,DocumentBuilderFactory可以设置是否校验、是否开启命名空间、是否忽略注释空白节点等,详细可以看上面源码注释。
  • 如果开启了xml格式校验,DocumentBuilder就要设置实体解析器,这里使用了构造函数传入的实体解析器,如果解析xml过程中检测到格式不对或者其他报错,则需要抛出异常信息,所以这里又设置了错误处理器ErrorHandler,对于错误和致命错误直接抛出异常,对于警告则忽略。

MyBatis解析配置文件的本质就是为了获得Configuration对象;
Configuration 对象可以理解是mybatis的XML配置文件在程序中的化身,是MyBatis非常重要的一个对象,里面封装了MyBatis的整个配置信息

建造者模式的使用

DefaultSqlSessionFactory 类的有参构造需传入 Mybatis 核心配置类 Configuration 的对象作为参数,而 Configuration 内容很多,初始化比较麻烦,因此使用了专门的建造者 XMLConfigBuilder 进行创建

把源码看过一遍之后我们大概可以看出来建造者模式的使用结构:

在这里插入图片描述

  • 在Mybatis环境的初始化过程中,SqlSessionFactoryBuilder会调用XMLConfigBuilder读取所有的MybatisMapConfig.xml和所有的Mapper.xml文件,构建Mybatis运行的核心对象Configuration对象,然后将该Configuration对象作为参数构建一个SqlSessionFactory对象。
  • 其中XMLConfigBuilder在构建Configuration对象时,也会调用XMLMapperBuilder用于读取*Mapper文件
  • 而XMLMapperBuilder会使用MapperAnnotationBuilder(注解开发)或者XMLStatementBuilder(xml开发)来读取和build所有的SQL语句。

其中在XMLConfigBuilder中的parseConfiguration方法中对Configuration的属性进行装配:
在这里插入图片描述
这里就对应了xml配置文件
在这里插入图片描述
通过以上源码,我们就能看出,在mybatis的配置文件中:

  • configuration节点为根节点。
  • 在configuration节点之下,我们可以配置10个子节点, 分别为:properties、typeAliases、plugins、objectFactory、objectWrapperFactory、settings、environments、databaseIdProvider、typeHandlers、mappers。顺序遵从dtd文件约束,解析配置文件完成了之后,都会装配到configuration
  • Configuration作用:mybatis核心的配置文件内容 ,使用xml转换bean

我们debug到这个方法,可以看到configuration对象的内部结构:
在这里插入图片描述

总结一下:

XMLConfigBuilder 类负责创建复杂对象 Configuration,可以视为具体建造者角色,而SqlSessionFactoryBuilder则是以封装式构建 SqlSessionFactory 实例,相当于简化的建造者模式。

打开SqlSession

第一层:

//第三步:打开SqlSession
SqlSession session = sqlSessionFactory.openSession();

第二层:

  • 调用openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)返回SqlSession 对象

第三层:

  • configuration.getEnvironment():从configuration配置对象中获取环境environment信息

    • 相当于我们xml文件中的
      在这里插入图片描述
    • java中的模型类:
      在这里插入图片描述
  • getTransactionFactoryFromEnvironment(environment):根据环境environment信息获取事务工厂TransactionFactory

  • transactionFactory.newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit):根据数据源、事务隔离级别、是否自动提交来创建事务。其本质就是new了一个JDBC事务
    在这里插入图片描述

  • Executor Configuration.newExecutor(Transaction transaction, ExecutorType executorType):根据执行器类型和事务创建执行器Executor对象

    • 默认使用ExecutorType.SIMPLE型
    • 如果配置了二级缓存,则会将执行器进行包装:executor = new CachingExecutor(executor)
      在这里插入图片描述
    • 将执行器加入拦截器链,循环遍历执行拦截器
      在这里插入图片描述
      • 这个interceptors是在xml文件中配置的
        在这里插入图片描述
  • DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit):根据configuration和Executor创建一个默认的DefaultSqlSession对象并返回。

然后我们来看看详细过程:
在这里插入图片描述

获取Mapper接口对象

//第四步:获取Mapper接口对象
UUserInfoMapper uUserInfoMapper = session.getMapper(UUserInfoMapper.class);

详细过程如下:
在这里插入图片描述

执行Mapper接口方法

List<Stu> stus = mapper.selectSome(1);

在这里插入图片描述

未完待续。。。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6.1.1 图:基本概念

一&#xff0c;基本概念 1.基本定义 &#xff08;1&#xff09;图的定义 顶点集不可以是空集&#xff0c;但边集可以是空集。 &#xff08;2&#xff09; 有向图的表示&#xff1a; 圆括号 无向图的表示&#xff1a; 尖括号 简单图、多重图&#xff1a; 简单图&#xff1a;…

基于 SpringBoot+WebSocket 无DB实现在线聊天室

0 项目说明 0.1 样例展示 0.2 源码地址 GitHub&#xff1a;https://github.com/ShiJieCloud/web-chat Gitee&#xff1a;https://gitee.com/suitbaby/web-chat GitCode&#xff1a;I’m Jie / web-chat GitCode 1 WebSocket 简介 1.1 HTTP 常用的 HTTP 协议是一种无状态…

刚进公司就负责项目,把老弟整蒙了!

刚进公司就负责项目&#xff0c;把老弟整蒙了&#xff01; 大家好&#xff0c;我是鱼皮&#xff0c;先把封面图送给大家&#xff1a; 又快到周末了&#xff0c;今天分享一些轻松的编程经验~ 还记得我学编程的老弟小阿巴么&#xff1f;他目前大二&#xff0c;听说最近刚刚找到…

Redis超详细入门手册教程!还不快来看看?

地址&#xff1a; RedisRedis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures …https://redis.io/ 1&#xff1a;NoSQL简介 1.1&#xff1a;数据库应用的演变历程 单…

线程的原子性、可见性、有序性及线程安全知识整理

要想保证线程安全&#xff0c;必须同时满足原子性、可见性、有序性。 一、定义 1.1 原子性 一个操作或者多个操作&#xff0c;要么全部执行&#xff0c;并且执行的过程不会被打断&#xff0c; 要么就全部不执行&#xff08;一个操作是不可被分割的&#xff09;。 Java中实现…

ApiPost简单使用

目录 环境与变量 设置与使用 随机参数变量 内置Mock字段随机参数 自定义随机参数 全局参数 使用手册 apipost可支持一键压测和自动化接口测试 环境与变量 设置与使用 设置 环境变量可设置环境名称、变量名称、变量初始值、URL&#xff1a; 可以在请求变量或者接口 URL…

攻防世界-web-simple js

题目描述&#xff1a;小宁发现了一个网页&#xff0c;但却一直输不对密码。(Flag格式为 Cyberpeace{xxxxxxxxx} ) 打开链接&#xff1a; 然后我们会发现不管我们输入什么密码&#xff0c;发现是都是这样的报错 1. 先用bp抓包看看&#xff0c;可以抓到这样的一串js脚本 看不懂…

matlab实现BP神经网络(完整DEMO)

本站原创文章&#xff0c;转载请说明来自《老饼讲解-BP神经网络》bp.bbbdata.com 目录 一、BP神经网络Demo代码 1.1 代码整体思路 1.2 BP神经网络Demo代码 二、运行结果 2.1 拟合曲线 2.2训练误差与预测误差 三、相关文章 3.1-BP的入门学习目录&#xff1a;老饼…

JavaScript经典教程(七)-- JavaScript初级

190&#xff1a;JavaScript初级内容 - DOM查询、插入内容、赋予样式等 1、DOM操作 DOM&#xff1a;节点&#xff0c;也就是html中的元素&#xff1b; DOM操作&#xff1a;其实就是节点元素的方法&#xff1b; &#xff08;1&#xff09;innerHTML - 返回元素内容 同时也可以…

关于maven

一、maven是什么 一个java项目构建工具 二、maven的作用 &#xff08;1&#xff09;依赖管理 不同框架整合&#xff0c;互相依赖jar包版本不同&#xff0c;版本不一样&#xff0c;程序跑起来就会报错。用maven管理jar包。 &#xff08;2&#xff09;跨平台构建项目 linux服…

数据结构学习记录——堆的建立(最大堆的建立、思路图解、代码实现、代码解释)

目录 最大堆的建立 方法1 方法2 思路图解 代码实现 代码解释 PercDown BuildHeap 最大堆的建立 建立最大堆&#xff1a;将已经存在的N个元素按最大堆的要求存放在一个一维数组中。 方法1 通过插入操作&#xff0c;将N个元素一个一个地插入到一个初始为空的堆中去。…

简述对象检测与图像分类与关键点检测区别

计算机视觉是人工智能的一个多元化领域&#xff0c;旨在检测和识别图像或视频的内容。大多数开始计算机视觉领域之旅的人的常见问题之一是&#xff1a;目标检测、图像分类和关键点检测之间有什么区别&#xff1f; 让我们先看看 什么是对象检测 对象检测是一种计算机视觉和图像…

excel中英文互译

在excel运行宏时弹出下面的提示&#xff1a; 无法运行“XXXXX”宏。可能是因为该宏在此工作薄中不可用&#xff0c;或者所有的宏都被禁用的错误提示 解决办法&#xff1a; 1、点击“文件”选项卡&#xff1b; 2、在选项卡界面窗口中选择“选项”按钮&#xff1b; 3、在“选项…

JavaScript实现在键盘输入按键,浏览器进行显示的代码

以下为实现在键盘输入按键&#xff0c;浏览器进行显示的代码和运行截图 目录 前言 一、在键盘输入按键&#xff0c;浏览器进行显示 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择&#xff0c;您可以在目录里进行快速查找&#xf…

智能汽车实验二(视觉传感器标定)

实验二 视觉传感器标定&#xff08;实验报告&#xff09; 【实验目的】 1、了解开源图像处理库OpenCV的结构&#xff0c;掌握OpenCV的基本使用方法。 2、了解开源图像处理库OpenCV的基本模块功能&#xff0c;掌握常用图像处理方法。 3、掌握摄像机标定算法&#xff0c;学会使用…

igraph的layout布局

做图论的社区检测&#xff0c;需要画图显示&#xff0c;用igraph可以进行可视化。 igraph有几个布局&#xff0c;分别如下&#xff1a; layout_with_dh &#xff1a; The Davidson-Harel layout algorithm Place vertices of a graph on the plane, according to the simulat…

113-Linux_安装c/c++开发库及连接mysql数据库

文章目录 一.安装c/c开发库二.连接mysql数据库三.用户的管理与授权 mysql数据库的安装 一.安装c/c开发库 安装开发c/c的库&#xff0c;命令&#xff1a;apt install libmysqlclient-dev 二.连接mysql数据库 #include<stdio.h> #include<mysql/mysql.h>void fun…

Python+Selenium4环境搭建

set集合 怎么把列表种相同的数据和不同的数据取出来 1.把列表转为set集合 2.按照集合的交集 selenium 自动化测试&#xff1a;自动化测试就是通过代码或者是工具模拟人的行为来进行对WEB&#xff08;APP&#xff09;来进行操作。 QTP (HP公司)&#xff1a;以录制回放的模式…

CSS进阶

01-复合选择器 定义&#xff1a;由两个或多个基础选择器&#xff0c;通过不同的方式组合而成。 作用&#xff1a;更准确、更高效的选择目标元素&#xff08;标签&#xff09;。 后代选择器 后代选择器&#xff1a;选中某元素的后代元素。 选择器写法&#xff1a;父选择器 …

学系统集成项目管理工程师(中项)系列19b_成本管理(下)

1. 成本估算 1.1. 编制完成项目活动所需资源的大致成本 1.2. 在设计阶段多做些额外的工作可能减少执行阶段和产品运行时的成本 1.3. 项目估算的准确性随着项目的进展而提高 1.3.1. 【19下选48】 1.4. 针对完成活动所需资源的可能成本进行的量化评估 1.5. 容易被忽视的主要…