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

Spring 整合 MyBatis 底层源码解析

大家好,我是柳岸花开。今天我们要讲的是 Spring 整合 MyBatis 的底层源码解析。希望大家能更深入理解 Spring 和 MyBatis 的整合原理,并应用到实际项目中。

由很多框架都需要和Spring进行整合,而整合的核心思想就是把其他框架所产生的对象放到Spring容器中,让其成为Bean。 ​

Mybatis框架可以单独使用,而单独使用Mybatis框架就需要用到Mybatis所提供的一些类构造出对应的对象,然后使用该对象,就能使用到Mybatis框架给我们提供的功能,和Mybatis整合Spring就是为了将这些对象放入Spring容器中成为Bean,只要成为了Bean,在我们的Spring项目中就能很方便的使用这些对象了,也就能很方便的使用Mybatis框架所提供的功能了。

一、Spring 和 MyBatis 简介

Spring

  • 一个开源框架,提供全面的基础设施支持,简化 Java 开发,特别是在企业级开发中。
  • 核心是控制反转(IoC)和面向切面编程(AOP)。

MyBatis

  • 优秀的持久层框架,支持自定义 SQL、存储过程及高级映射。
  • 避免了大部分 JDBC 代码和手动设置参数及获取结果集的麻烦。

Mybatis-Spring底层源码执行流程

  1. 通过@MapperScan导入了MapperScannerRegistrar类
  2. MapperScannerRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以Spring在启动时会调用MapperScannerRegistrar类中的registerBeanDefinitions方法
  3. 在registerBeanDefinitions方法中注册一个MapperScannerConfigurer类型的BeanDefinition
  4. 而MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,所以Spring在启动过程中时会调用它的postProcessBeanDefinitionRegistry()方法
  5. 在postProcessBeanDefinitionRegistry方法中会生成一个ClassPathMapperScanner对象,然后进行扫描
  6. 设置ClassPathMapperScanner对象可以扫描到接口,因为在Spring中是不会扫描接口的
  7. 同时因为ClassPathMapperScanner中重写了isCandidateComponent方法,导致isCandidateComponent只会认为接口是备选者Component
  8. 通过利用Spring的扫描后,会把接口扫描出来并且得到对应的BeanDefinition
  9. 接下来把扫描得到的BeanDefinition进行修改,把BeanClass修改为MapperFactoryBean,把AutowireMode修改为byType
  10. 扫描完成后,Spring就会基于BeanDefinition去创建Bean了,相当于每个Mapper对应一个FactoryBean
  11. 在MapperFactoryBean中的getObject方法中,调用了getSqlSession()去得到一个sqlSession对象,然后根据对应的Mapper接口生成一个Mapper接口代理对象,这个代理对象就成为Spring容器中的Bean
  12. sqlSession对象是Mybatis中的,一个sqlSession对象需要SqlSessionFactory来产生
  13. MapperFactoryBean的AutowireMode为byType,所以Spring会自动调用set方法,有两个set方法,一个setSqlSessionFactory,一个setSqlSessionTemplate,而这两个方法执行的前提是根据方法参数类型能找到对应的bean,所以Spring容器中要存在SqlSessionFactory类型的bean或者SqlSessionTemplate类型的bean。
  14. 如果你定义的是一个SqlSessionFactory类型的bean,那么最终也会被包装为一个SqlSessionTemplate对象,并且赋值给sqlSession属性
  15. 而在SqlSessionTemplate类中就存在一个getMapper方法,这个方法中就产生一个Mapper接口代理对象
  16. 到时候,当执行该代理对象的某个方法时,就会进入到Mybatis框架的底层执行流程。

Spring整合Mybatis后一级缓存失效问题

Mybatis中的一级缓存是基于SqlSession来实现的,所以在执行同一个sql时,如果使用的是同一个SqlSession对象,那么就能利用到一级缓存,提高sql的执行效率。 ​

在Spring整合Mybatis后,如果执行某个方法时,该方法上没有加@Transactional注解,也就是没有开启Spring事务,那么后面在执行具体sql时,每执行一个sql时都会新生成一个SqlSession对象来执行该sql,这就是我们说的一级缓存失效(也就是没有使用同一个SqlSession对象),而如果开启了Spring事务,那么该Spring事务中的多个sql,在执行时会使用同一个SqlSession对象,从而一级缓存生效。 ​

Spring整合Mybatis后一级缓存失效并不是问题,是正常的实现,因为一个方法如果没有开启Spring事务,那么在执行sql时候,那就是每个sql单独一个事务来执行,也就是单独一个SqlSession对象来执行该sql,如果开启了Spring事务,那就是多个sql属于同一个事务,那自然就应该用一个SqlSession来执行这多个sql。所以,在没有开启Spring事务的时候,SqlSession的一级缓存并不是失效了,而是存在的生命周期太短了(执行完一个sql后就被销毁了,下一个sql执行时又是一个新的SqlSession了)。

总结

今天我们深入解析了 Spring 和 MyBatis 整合的核心组件及其底层实现原理。希望大家通过这次课程能够对 Spring 和 MyBatis 有更深入的理解,并能在实际项目中灵活运用。

👇关注我,下期了解👇

Spring AOP底层源码解析

alt

回复 222,获取Java面试题合集

关于我

一枚爱折腾的Java程序猿,专注Spring干货。把路上的问题记录下来,帮助那些和我一样的人。

好奇心强,喜欢并深入研究古天文。

崇尚 个人系统创建,做一些时间越长越有价值的事情。思考 把时间留下来 又 每刻都是新的。

相关文章:

  • 条件语句与循环结构
  • PyFlink
  • 探索乡村振兴新模式:发挥科技创新在乡村振兴中的引领作用,构建智慧农业体系,助力美丽乡村建设
  • 算法笔记 图论和优先级队列的笔记
  • CSS从入门到精通——动画:CSS3动画执行次数和逆向播放
  • 中间件复习之-分布式存储系统
  • C#防止多次注册事件
  • 学习笔记——网络管理与运维——SNMP(SNMP版本)
  • uniapp如何实现跳转
  • GenICam标准(六)
  • MySQL的三种重要的日志
  • Vue3 和 Vue2 对比分析及示例代码解析(初级)
  • Python **运算符(python**kwargs:参数解包)(kwargs:keyword arguments)
  • 10:Hello, World!的大小
  • 小程序无法调用服务端问题排查
  • 2018一半小结一波
  • Apache的基本使用
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • Kibana配置logstash,报表一体化
  • leetcode-27. Remove Element
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • SpiderData 2019年2月25日 DApp数据排行榜
  • zookeeper系列(七)实战分布式命名服务
  • 测试如何在敏捷团队中工作?
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 每天一个设计模式之命令模式
  • 算法之不定期更新(一)(2018-04-12)
  • const的用法,特别是用在函数前面与后面的区别
  • 带你开发类似Pokemon Go的AR游戏
  • 整理一些计算机基础知识!
  • ​【已解决】npm install​卡主不动的情况
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • (03)光刻——半导体电路的绘制
  • (Redis使用系列) SpringBoot 中对应2.0.x版本的Redis配置 一
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (译) 理解 Elixir 中的宏 Macro, 第四部分:深入化
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .cn根服务器被攻击之后
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET下的多线程编程—1-线程机制概述
  • :“Failed to access IIS metabase”解决方法
  • @Conditional注解详解
  • @EnableAsync和@Async开始异步任务支持
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [4]CUDA中的向量计算与并行通信模式
  • [AIGC] Kong:一个强大的 API 网关和服务平台
  • [C++]类和对象(中)
  • [Codeforces] number theory (R1600) Part.11
  • [codeforces]Levko and Permutation
  • [daily][archlinux][game] 几个linux下还不错的游戏