思维导图手撕MyBatis源码

news2024/11/18 10:46:57

文章目录

  • 前置准备
  • 通过类加载器读取配置文件流
  • 创建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);

在这里插入图片描述

未完待续。。。

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

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

相关文章

Node 【Buffer 与 Stream】

文章目录 &#x1f31f;前言&#x1f31f;Buffer&#x1f31f; Buffer结构&#x1f31f; 什么时候用Buffer&#x1f31f; Buffer的转换&#x1f31f; Buffer使用&#x1f31f; 创建Buffer&#x1f31f; 字符串转Buffer&#x1f31f; Buffer转字符串&#x1f31f; 拼接Buffer&am…

微信小程序登录注册页面

// login.js // 获取应用实例 var app getApp() var api require("../../utils/api.js")Page({data: {motto: zhenbei V1.0.0,userInfo: {},hasUserInfo: false,disabled: true,btnstate: default,username: ,password: ,canIUse: wx.canIUse(button.open-type.get…

UE4/5 C++网络服务器编程纪录【零】--准备篇

前言 之前利用业余时间重新复习UE4/5的C开发&#xff0c;闲来无事做了个基于独立服务器的多人在线&#xff08;目前限定客户数量是20人以内&#xff09;DEMO&#xff0c;核心功能在我之前发的B站视频里面有&#xff0c;战斗、动作、交互以及场景演示都有了&#xff0c;有朋友看…

Linux使用:环境变量指南和CPU和GPU利用情况查看

Linux使用&#xff1a;环境变量指南和CPU和GPU利用情况查看 Linux环境变量初始化与对应文件的生效顺序Linux的变量种类设置环境变量直接运行export命令定义变量修改系统环境变量修改用户环境变量修改环境变量配置文件 环境配置文件的区别profile、 bashrc、.bash_profile、 .ba…

函数(有点难,要注重实战)

目录 1. 函数是什么2. C语言中函数的分类2.1 库函数2.1.1 如何学会使用库函数&#xff1f; 2.2 自定义函数 3. 函数的参数3.1 实际参数&#xff08;实参&#xff09;&#xff1a;3.2 形式参数&#xff08;形参&#xff09;&#xff1a; 4. 函数的调用&#xff1a;4.1 传值调用4…

Spark SQL实战(08)-整合Hive

1 整合原理及使用 Apache Spark 是一个快速、可扩展的分布式计算引擎&#xff0c;而 Hive 则是一个数据仓库工具&#xff0c;它提供了数据存储和查询功能。在 Spark 中使用 Hive 可以提高数据处理和查询的效率。 场景 历史原因积累下来的&#xff0c;很多数据原先是采用Hive…

Node内置模块 【url模块与queryString】

文章目录 &#x1f31f;前言&#x1f31f;url 模块&#x1f31f; URL各部分说明&#x1f31f; 将URL字符串转换为对象&#x1f31f; 将对象格式化为URL字符串&#xff1a;url.format(urlObj)&#x1f31f; URL路径处理&#xff1a;url.resolve(from, to) &#x1f31f; querySt…

MySQL-四大类日志

目录 &#x1f341;MySQL日志分为4大类 &#x1f341;错误日志 &#x1f343;修改系统配置 &#x1f341;二进制日志 &#x1f343;查看二进制日志 &#x1f343;删除二进制日志 &#x1f343;暂时停止二进制日志的功能 &#x1f341;事务日志(或称redo日志) &#x1f341;慢查…

SSM整合、环境配置以及详细综合测试(单表查询、多表查询和数据分页、前后端分离、Vue3)

SSM整合、环境配置以及基础综合测试 准备&#xff1a;创建maven项目以及项目框架准备 SSM整合简介 介绍: SSM(SpringSpringMVCMyBatis) 整合&#xff0c;就是三个框架协同开发。Spring整合Mybatis就是将Mybatis核心配置文件当中数据源的配置、事务处理、以及工厂的配置&…

OpenGL入门教程之 深入三角形

一、引言 本教程使用GLEW和GLFW库。  通过本教程&#xff0c;你能轻松的、深入的理解OpenGL如何绘制一个三角形。  如果你不了解OpenGL是什么&#xff0c;可以阅读OpenGL深入理解。 二、基本函数和语句介绍 通过阅读以下的函数&#xff0c;你的大脑里能留下关于OpenGL基本函…

通过CSIG—走进合合信息探讨生成式AI及文档图像处理的前景和价值

一、前言 最近有幸参加了由中国图象图形学学会&#xff08;CSIG&#xff09;主办&#xff0c;合合信息、CSIG文档图像分析与识别专业委员会联合承办的“CSIG企业行——走进合合信息”的分享会&#xff0c;这次活动以“图文智能处理与多场景应用技术展望”为主题&#xff0c;聚…

安全防御第四天:防病毒网关

一、恶意软件 1.按照传播方式分类 &#xff08;1&#xff09;病毒 病毒是一种基于硬件和操作系统的程序&#xff0c;具有感染和破坏能力&#xff0c;这与病毒程序的结构有关。病毒攻击的宿主程序是病毒的栖身地&#xff0c;它是病毒传播的目的地&#xff0c;又是下一次感染的出…

尚融宝21-整合springcloud

目录 一、整合注册中心nacos 二、整合openFeign &#xff08;一&#xff09;准备工作 &#xff08;二&#xff09;导入依赖 &#xff08;三&#xff09;接口的远程调用 &#xff08;四&#xff09;配置超时控制和日志打印 三、整合Sentinel 四、整合gateway服务网关 …

【Spring从成神到升仙系列 五】从根上剖析 Spring 循环依赖

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小黄&#xff0c;独角兽企业的Java开发工程师&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#x1f4d5;系列专栏&#xff1a;Java设计模式、数据结构和算法、Kafka从入门到成神、Kafka从成神到升仙…

基于SpringBoot+Vue家乡特色推荐系统

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

【李老师云计算】HBase+Zookeeper部署及Maven访问(HBase集群实验)

索引 前言1. Zookeeper1.1 主机下载Zookeeper安装包1.2 主机解压Zookeeper1.3 ★解决解压后文件缺失1.4 主机配置Zookeeper文件1.4.1 配置zoo_sample.cfg文件1.4.2 配置/data/myid文件 1.5 主机传输Zookeeper文件到从机1.6 从机修改Zookeeper文件1.6.1 修改zoo.cfg文件1.6.2 修…

一文带你了解MySQL的前世今生,架构,组成部分,特点,适用场景

文章目录 一、MySQL的由来二、MySQL的架构2.1 客户端2.2 服务器 三、 MySQL的主要组成部分3.1 连接管理器3.2 查询缓存3.3 解析器3.4 查询优化器3.5 执行器3.6 存储引擎 四、MySQL的特点五、MySQL的应用场景六、总结 一、MySQL的由来 MySQL最初是由瑞典公司MySQL AB的Michael …

4年功能测试,我一进阶python接口自动化测试,跳槽拿了20k......

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 很多人在这求职市…

让ChatGPT告诉你Java的发展前景

Java版电商购物系统项目实战 最近很多人问我Java的发展前景怎么样&#xff1f;该怎么学Java基础&#xff1f;java这么卷还该不该学等等。那今天老王以电商场景为例&#xff0c;再结合ChatGPT的回答和大家聊的一下Java有哪些应用前景和技术层面的落地方案。&#xff08;在收获干…

【Spring】-- 02 -- Spring中Bean的配置、作用域

一、Bean的配置 Spring用于生产和管理Spring容器中的Bean&#xff0c;需要开发者对Spring的配置文件进行配置。在实际开发中&#xff0c;最常采用XML格式的配置方式&#xff0c;即通过XML文件来注册并管理Bean之间的依赖关系。 在Spring中&#xff0c;XML配置文件的根元素是…