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

Spring之整合Mybatis底层源码解析

整合核心思路

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

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

Mybatis-Spring 1.3.2版本底层源码执行流程

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

Spring整合Mybatis之后SQL执行流程:

Mybatis-Spring 2.0.6版本(最新版)底层源码执行流程

  1. 通过@MapperScan导入了MapperScannerRegistrar类
  2. MapperScannerRegistrar类实现了ImportBeanDefinitionRegistrar接口,所以Spring在启动时会调用MapperScannerRegistrar类中的registerBeanDefinitions方法
  3. 在registerBeanDefinitions方法中注册一个MapperScannerConfigurer类型的BeanDefinition
  4. 而MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor接口,所以Spring在启动过程中时会调用它的postProcessBeanDefinitionRegistry()方法
  5. 在postProcessBeanDefinitionRegistry方法中会生成一个ClassPathMapperScanner对象,然后进行扫描
  6. 后续的逻辑和1.3.2版本一样。

带来的好处是,可以不使用@MapperScan注解,而可以直接定义一个Bean,比如:

@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();mapperScannerConfigurer.setBasePackage("com.luban");return mapperScannerConfigurer;
}

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

先看下图:
Spring整合Mybatis之后SQL执行流程:

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了)。
 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 万字文档带你走进Python的世界
  • 一图打尽C++内存分区(分段)
  • 力扣9.2
  • World of Warcraft [CLASSIC][80][Grandel]Sapphire Hive Drone
  • Nvidia股价前景引投资者情绪波动:杠杆ETF数据透视市场风向
  • k8s集群搭建
  • 工业软件架构4:(QT和C++实现)
  • 二十五、go语言的通道
  • 代码随想录算法训练营第32天|509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
  • 8.28路虎女事件
  • 掌握 JavaScript 解构赋值的指南
  • 蜜罐网络MHN安装过程中的坑
  • Pytorch实现多层LSTM模型,并增加emdedding、Dropout、权重共享等优化
  • Windows 下载安装RabbitMQ
  • 干货分享:推荐四大在线翻译神器!
  • Android Volley源码解析
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Javascript设计模式学习之Observer(观察者)模式
  • Java多线程(4):使用线程池执行定时任务
  • Java精华积累:初学者都应该搞懂的问题
  • js继承的实现方法
  • Node + FFmpeg 实现Canvas动画导出视频
  • Vue--数据传输
  • 对象引论
  • 记录一下第一次使用npm
  • 前端知识点整理(待续)
  • 优秀架构师必须掌握的架构思维
  • 原生Ajax
  • 正则学习笔记
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #{}和${}的区别?
  • #162 (Div. 2)
  • #宝哥教你#查看jquery绑定的事件函数
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (14)Hive调优——合并小文件
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (Note)C++中的继承方式
  • (八)Spring源码解析:Spring MVC
  • (二)windows配置JDK环境
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (一)Thymeleaf用法——Thymeleaf简介
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • .NET Core引入性能分析引导优化
  • .NET delegate 委托 、 Event 事件,接口回调
  • .net framework4与其client profile版本的区别
  • .NET NPOI导出Excel详解
  • .sdf和.msp文件读取
  • @Autowired 与@Resource的区别
  • @Autowired和@Resource装配
  • @Not - Empty-Null-Blank