当前位置: 首页 > news >正文

2. Spring Boot 自动配置 Mybatis 流程

1. Spring Boot 自动配置 Mybatis

自动配置过程中做了3个主要bean的创建及很重要的一些事情。

  1. sqlSessionFactory、sqlSessionTemplate、MapperScannerConfigurer 等配置bean的创建。
  2. sqlSessionFactory:解析 xml配置文件,并将MappedStatement放入到HashMap中。
  3. sqlSessionTemplate:代理了 DefaultSqlSession,增强了Session的创建获取、关闭、事务等能力。
  4. MapperScannerConfigurer:扫描@Mapper注解,并生成这些类的BeanDefinition放入到注册表中。
自动配置

约定大于配置,缺省的配置看这个注解 @EnableConfigurationProperties({MybatisProperties.class})。这个注解中引入了MybatisProperties类,包含了一些默认的配置。

@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {}

MybatisAutoConfiguration的主要属性有:

  1. MybatisProperties:yaml文件中的属性配置
  2. Interceptor[] :拦截器数组
  3. TypeHandler[] :类型解析器等

构造方法:

  1. 从 yaml 文件中获取 mybatis 前缀的属性封装成对象​MybatisProperties​,赋值给 properties 。
  2. 获取拦截器
  3. 获取typeHandlers
  4. 其他。。。
创建 sqlSessionFactory

前提:

  1. 依赖DataSource 数据源 @ConditionalOnSingleCandidate(DataSource.class)。要求 BeanFactory 中存在指定类并且可以确定单个候选项才会匹配成功
  2. 在数据源完成自动配置之后配置 sqlSessionFactory = new SqlSessionFactoryBean().getObject();

正文:

  1. 创建一个工厂bean:​MybatisSqlSessionFactoryBean​​

  2. 工厂 bean 设置数据源dataSource。依赖注入,此时容器中已经有了dataSource,直接拿来用。

  3. 初始化配置属性

    1. 如果有配置 mybatis-config.xml 则设置configLocation 属性。
    2. 应用yaml 文件中嵌套配置 configuration到 factoryBean。
    3. TypeHandler
    4. 拦截器
  4. 通过工厂Bean的getObject方法获取sqlSessionFactory。

    1. 对关键配置做断言处理:dataSource​、sqlSessionFactoryBuilder​、configuration​、​configLocation

    2. buildSqlSessionFactory​:开始构建sqlSessionFactory。

      1. 如果配置项 mapperLocation不为空,循环解析每一个 mapper.xml文件

      2. XMLMapperBuilder.parse() 解析xml 文件

        1. 如果没有解析过该 xml 文件,则进行解析,如果解析过,直接跳过。

        2. configurationElement​​​​​解析mapper 节点

          <mapper namespace="com.pansnow.changcheng.mapper.UserMapper"><select id="queryUserList" resultType="com.pansnow.changcheng.pojo.User">select *from user</select><insert id="addUser" parameterType="com.pansnow.changcheng.pojo.User">insert into user(id, name, pwd)values (#{id}, #{name}, #{pwd});</insert><update id="updateUser" parameterType="com.pansnow.changcheng.pojo.User">update userset name=#{name},pwd=#{pwd}where id = #{id};</update><delete id="deleteUser" parameterType="int">deletefrom userwhere id = #{id};</delete>
          </mapper>
          
        3. namespace判空。namespace 为 mapper 接口类的 String 字符串

        4. 解析 parameterMap 和 resultMap节点

        5. 解析 sql节点

        6. 解析 select|insert|update|delete

      3. 将该文件添加到已解析集合中。

        protected final Set<String> loadedResources;
        if (!this.configuration.isResourceLoaded(this.resource)) {...this.configuration.addLoadedResource(this.resource);...
        }
        
      4. 将 mapper 类添加到 mapper注册表中。

        private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap();this.knownMappers.put(type, new MapperProxyFactory(type));
        
        1. knownMapper是一个mapper接口类和他的代理工厂的一个映射。

        2. 解析 mapper 类上的注解@Select、@SelectProvider、@ResultMap 等注解,用于解析 mapper 类中方法上的 SQL 语句。

        3. 解析方法上的xml文件中的 SQL语句 parseStatement。

          1. 具体的解析过程就不谈了,太复杂,先不看了。
          2. MybatisSqlSessionFactoryBean​​中有一个属性mappedStatements​​。这是一个 HashMap
          3. 将解析过后的MappedStatement​​添加到 map 中
创建sqlSessionTemplate
  1. 使用 jdk 动态代理,创建SqlSessionProxy,增强逻辑为SqlSessionInterceptor​。代理了SqlSession的创建和获取、事务、关闭。即在调用SqlSession接口中的每一个方法时,都会调用SqlSessionInteceptor的invoke逻辑。

  2. SqlSessionInterceptor​的逻辑为:

    1. 创建SqlSession。使用 selSessionFactory

      代理对象是如何获取defaultSqlSession ,在代理方法中通过SqlSessionUtils 的方法获取SqlSession

      • 它会首先获取SqlSessionHolder,SqlSessionHolder用于在TransactionSynchronizationManager中保持当前的SqlSession。
      • 如果holder不为空,并且holder被事务锁定,则可以通过holder.getSqlSession()方法,从当前事务中获取sqlSession,即 Fetched SqlSession from current transaction。
      • 如果不存在holder或没有被事务锁定,则会创建新的sqlSession,即 Creating a new SqlSession,通过sessionFactory.openSession()方法。
      • 如果当前线程的事务是活跃的,将会为SqlSession注册事务同步,即 Registering transaction synchronization for SqlSession。
      SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
      
      1. 如果 session 为 null,

        1. 利用事务工厂创建一个事务,
        2. 新建一个 Executor:这个是干嘛的,不太清楚哇。
        3. 新建一个 DefaultSqlSession。
        4. 创建sqlSessionHolder 将 sqlSession 包起来。
        5. 将sqlSessionHolder存放到TransactionSynchronizationManager​的synchronizations​中。synchronizations​是一个 set 集合。
    2. 调用业务方法

    3. 如果有事务,提交事务

    4. 关闭 session。关闭前会释放 holder。​holder.released();

      SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
      
创建MapperScannerRegistrarNotFoundConfiguration

主要在于根据配置创建MapperScannerConfigurer​,

@Import({AutoConfiguredMapperScannerRegistrar.class}) 这个AutoConfiguredMapperScannerRegistrar类非常关键,因为他在扫描@Mapper 注解

  1. BeanDefinitionBuilder​:创建MapperScannerConfigurer​的 BeanDefinitionBuilder
  2. 设置扫描注解类:Mapper.class
  3. 设置扫描包路径
  4. 设置sqlSessionFactoryBeaName
  5. 设置 sqlSessionTemplateBeanName
  6. 注册MapperScannerConfigurer​到注册表中
MapperScannerConfigurer

实现了 BeanDefinitionRegistryPostProcessor ,工作在bean 定义的注册阶段。

扫描@Mapper 注解,为什么需要单独处理呢?因为 Mapper 注解是 mybatis 自定义注解,和 Component 注解没有关系。这个类会将@Mapper 注解下的类也实例化后放入到 Spring 容器中。

负责扫描Mapper接口的扫描器为ClassPathMapperScanner​,他是ClassPathBeanDefinitionScanner​的子类。ClassPathMapperScanner​扫描到注解类后,会为其生成BeanDefinition。这里生成的是一个MapperFactoryBean的bean定义。

  1. 生成bean定义的时候,将bean定义的name设置为userMapper。但是其类型设置为了MapperFactoryBean。
  2. mapperInterface​ 设置为了 com.pansnow.changcheng.mapper.UserMapper
  3. factoryBeanObjectType​设置为了 com.pansnow.changcheng.mapper.UserMapper
  4. 加了个sqlSessionTemplate​的属性,引用指向容器中的bean:sqlSessionTemplate

然后在后期创建bean的时候,MapperFactoryBean会执行getObject方法

  1. knownMapper是一个mapper接口类和他的代理工厂的一个映射。

  2. MapperProxyFactory代理工厂创建mapperProxy 代理mapper接口。

    this.getSqlSession().getMapper(this.mapperInterface);||\||/
    this.mapperRegistry.getMapper(type, sqlSession);||\||/
    MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
    return mapperProxyFactory.newInstance(sqlSession);
    
  3. mapperProxy在执行方法的时候,会从DefaultSqlSession的Configuration中获取方法对应的MappedStatement。接下来就很明白了。

相关文章:

2. Spring Boot 自动配置 Mybatis 流程

1. Spring Boot 自动配置 Mybatis 自动配置过程中做了3个主要bean的创建及很重要的一些事情。 sqlSessionFactory、sqlSessionTemplate、MapperScannerConfigurer 等配置bean的创建。sqlSessionFactory&#xff1a;解析 xml配置文件&#xff0c;并将MappedStatement放入到Has…...

Nginx配置反向代理实例一

Mac 安装Nginx教程 提醒一下&#xff1a;下面实例讲解是在Mac系统演示的&#xff1b; 反向代理实例一实现的效果 在浏览器地址栏输入www.testproxy.com, 跳转到系统Tomcat主页面。 第一步&#xff1a;在系统的 hosts 文件进行ip和域名对应关系的配置。 Mac 系统修改Hosts文…...

训练自己的GPT2

训练自己的GPT2 1.预训练与微调2.准备工作2.在自己的数据上进行微调 1.预训练与微调 所谓的预训练&#xff0c;就是在海量的通用数据上训练大模型。比如&#xff0c;我把全世界所有的网页上的文本内容都整理出来&#xff0c;把全人类所有的书籍、论文都整理出来&#xff0c;然…...

etcd储存安装

目录 etcd介绍: etcd工作原理 选举 复制日志 安全性 etcd工作场景 服务发现 etcd基本术语 etcd安装(centos) 设置&#xff1a;etcd后台运行 etcd 是云原生架构中重要的基础组件&#xff0c;由 CNCF 孵化托管。etcd 在微服务和 Kubernates 集群中不仅可以作为服务注册…...

如何彻底卸载Microsoft Edge浏览器

一、引语 随着微软推出全新的Edge浏览器&#xff0c;许多用户可能想要尝试或完全切换到其他浏览器。在这篇文章中&#xff0c;我们将向您介绍如何彻底卸载Microsoft Edge浏览器&#xff0c;以确保您的系统干净整洁。 二、通过系统设置卸载 1、首先&#xff0c;右键单击桌面上…...

Transformers 2023年度回顾 :从BERT到GPT4

人工智能已成为近年来最受关注的话题之一&#xff0c;由于神经网络的发展&#xff0c;曾经被认为纯粹是科幻小说中的服务现在正在成为现实。从对话代理到媒体内容生成&#xff0c;人工智能正在改变我们与技术互动的方式。特别是机器学习 (ML) 模型在自然语言处理 (NLP) 领域取得…...

判断两个对象某些字段的值是否相同

1、借助mybatis plus的方法 import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; import lombok.SneakyThrows; import o…...

TYPE-C接口取电芯片介绍和应用场景

随着科技的发展&#xff0c;USB PDTYPE-C已经成为越来越多设备的充电接口。而在这一领域中&#xff0c;LDR6328Q PD取电芯片作为设备端协议IC芯片&#xff0c;扮演着至关重要的角色。本文将详细介绍LDR6328Q PD取电芯片的工作原理、应用场景以及选型要点。 一、工作原理 LDR63…...

基于TI TPSXX系列 Buck电路应用计算-外围器件详细计算过程

TPS54202 Buck电路应用计算 1、电气特性2、内部框图3、典型应用电路4、设计需求5、计算EN引脚电阻6、FB引脚电阻估算7、查看反馈电压电压基准8、输入电容计算10、FB引脚反馈电阻计算11、功率电感计算12、输出电容计算13、前馈电容计算15、Layout布局TPS54202-中文版 1、电气特…...

NOIP2012提高组day1-T3:开车旅行

题目链接 [NOIP2012 提高组] 开车旅行 题目描述 小 A \text{A} A 和小 B \text{B} B 决定利用假期外出旅行&#xff0c;他们将想去的城市从 1 1 1 到 n n n 编号&#xff0c;且编号较小的城市在编号较大的城市的西边&#xff0c;已知各个城市的海拔高度互不相同&#xf…...

Golang Web框架性能对比

Golang Web框架性能对比 github star排名依次: Gin Beego Iris Echo Revel Buffalo 性能上gin、iris、echo网上是给的数据都是五星&#xff0c;beego三星&#xff0c;revel两星 beego是国产&#xff0c;有中文文档,文档齐全 根据star数&#xff0c;性能&#xff0c;易用程度…...

【OCR】 - Tesseract OCR在mac系统中安装

Tesseract OCR 在Mac环境下安装Tesseract OCR&#xff08;Optical Character Recognition&#xff09;通常可以通过Homebrew包管理器进行。以下是安装步骤&#xff1a; 安装Homebrew 如果你还没有安装Homebrew&#xff0c;请访问 https://brew.sh/ 并按照页面上的说明安装。…...

了解不同方式导入导出的速度之快

目录 一、用工具导出导入 Navicat&#xff08;速度慢&#xff09; 1.1、导入&#xff1a; 共耗时&#xff1a; 1.2、导出表 共耗时&#xff1a; 二、用命令语句导出导入 2.1、mysqldump速度快 导出表数据和表结构 共耗时&#xff1a; 只导出表结构 导入 共耗时&…...

2024年第九届计算机与通信系统国际会议(ICCCS2024) ,邀您相约西安!

会议官网: ICCCS2024 | Xian China 时间: 2024年4月19-22日 地点: 中国西安 会议简介&#xff1a; 近年来&#xff0c;信息通信在不断发展&#xff0c;为计算机网络的进步与发展提供了先进可靠的技术支持。随着计算机网络与通信技术的深入发展&#xff0c;计算机通信技术、数…...

获取直播间的最新评论 - python 取两个list的差集

python 取两个list的差集 作用&#xff1a;比如我要获取评论区列表&#xff0c;先获取了一遍&#xff0c;这个时候有人评论了几条&#xff0c;我再获取一遍后&#xff0c;找出多的那几条 使用set数据类型来取两个列表的差集。差集表示仅包含在第一个列表中而不在第二个列表中…...

2023年度总结:但行前路,不负韶华

​ &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;Vir2021GKBS &#x…...

智数融合|低代码入局,推动工业数字化转型走"深"向"实"

当下&#xff0c;“数字化、智能化”已经不再是新鲜词汇。事实上&#xff0c;早在几年前&#xff0c;就有企业开始大力推动数字化转型&#xff0c;并持续进行了一段时间。一些业内人士甚至认为&#xff0c;“如今的企业数字化已经走过了成熟期&#xff0c;进入了深水区。” 但事…...

初学者的基本 Python 面试问题和答案

文章目录 专栏导读1、什么是Python&#xff1f;列出 Python 在技术领域的一些流行应用。2、在目前场景下使用Python语言作为工具有什么好处&#xff1f;3、Python是编译型语言还是解释型语言&#xff1f;4、Python 中的“#”符号有什么作用&#xff1f;5、可变数据类型和不可变…...

支持向量机(Support Vector Machines,SVM)

什么是机器学习 支持向量机&#xff08;Support Vector Machines&#xff0c;SVM&#xff09;是一种强大的机器学习算法&#xff0c;可用于解决分类和回归问题。SVM的目标是找到一个最优的超平面&#xff0c;以在特征空间中有效地划分不同类别的样本。 基本原理 超平面 在二…...

golang一个轻量级基于内存的kv存储或缓存

golang一个轻量级基于内存的kv存储或缓存 go-cache是一个轻量级的基于内存的key:value 储存组件&#xff0c;类似于memcached&#xff0c;适用于在单机上运行的应用程序。 它的主要优点是&#xff0c;本质上是一个具有过期时间的线程安全map[string]interface{}。interface的结…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【JVM面试篇】高频八股汇总——类加载和类加载器

目录 1. 讲一下类加载过程&#xff1f; 2. Java创建对象的过程&#xff1f; 3. 对象的生命周期&#xff1f; 4. 类加载器有哪些&#xff1f; 5. 双亲委派模型的作用&#xff08;好处&#xff09;&#xff1f; 6. 讲一下类的加载和双亲委派原则&#xff1f; 7. 双亲委派模…...