mybatis是如何集成到spring的之SqlSessionFactoryBean

2023-11-16

1 前言

1.1 集成spring前使用mybatis的方式

mybatis单独使用时,一般的写法如下所示:

// mybatis初始化
String resource = "mybatis-config.xml";  
InputStream inputStream = Resources.getResourceAsStream(resource);  
// 读取配置文件,创建SqlSessionFactory 
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

// 打开SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();  

// 执行SQL语句
List list = sqlSession.selectList("com.gameloft9.demo.dataaccess.dao.system.UserMapper.getByLoginName");

1.2 集成mybatis到spring的关键步骤

将mybatis集成到spring之后,就可以被spring的ioc容器托管,再也不用自己创建SqlSessionFactory 、打开SqlSession等操作。具体的集成方法可以参考之前写的文章:spring集成mybatis进行数据库访问,其中最重要的配置就是定义好SqlSessionFactoryBean,如下所示:

<!--mybatis sqlSeesionFactory配置-->
		<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
			<property name="dataSource" ref="dataSource" />
			<property name="configLocation" value="classpath:mybatis-config.xml" />
			<property name="mapperLocations" value="classpath:mapper/*Mapper.xml" />
			<property name="typeAliasesPackage" value="com.gameloft9.demo.dataaccess.model" />
		</bean>

因此想要了解spring集成mybatis的原理,就应该从SqlSessionFactoryBean入手。

2 SqlSessionFactoryBean对象分析

SqlSessionFactoryBean,顾名思义跟SqlSessionFactory有着莫大的关系,它的类结构如下所示:
在这里插入图片描述
SqlSessionFactoryBean实现了InitializingBean接口,我们知道InitializingBean在Bean的生命周期里面扮演了重要的角色,spring创建bean的流程大概是:
1、创建beanFactory
2、加载beanDefinition
3、通过反射创建bean实例
4、bean的生命周期扩展点调用
其中第4步骤又包含:
5、如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
6、如果bean实现IntializingBean了,调用它的afterPropertySet方法。
7、如果bean定义了init-method,调用init方法
8、如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
9、如果bean实现了 DisposableBean,它将调用destroy()方法。
10、如果bean定义了destroy-method,调用destroy方法。
因此在我们xml配置好的dataSource,configLocation等属性设置好后,SqlSessionFactoryBean就在afterPropertySet()方法里面对SqlSessionFactory进行初始化。
在这里插入图片描述

2.1 buildSqlSessionFactory做了什么事情?

buildSqlSessionFactory里面就是具体怎么创建SqlSeesionFactory的,代码流程比较长,我们用一个简单时序图来展示:
在这里插入图片描述
在解析完各种配置后,调用了return this.sqlSessionFactoryBuilder.build(configuration);来创建buildSqlSessionFactory,是不是和之前的方式很类似了?只是一个是入参是resource,一个是我们解析后的配置configuration对象。

2.2 为什么是SqlSessionFactoryBean却可以使用SqlSessionFactory?

我们注册的是SqlSessionFactoryBean这个bean,为什么却说SqlSessionFactory也成为了spring的bean呢?因为我们的SqlSessionFactoryBean还实现了FactoryBean这个接口。

Spring 中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean 即 FactoryBean。FactoryBean跟普通Bean不同,其返回的对象不是指定类的一个实例,而是该FactoryBean的getObject方法所返回的对象。
一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。

然后回到maybatis这里,我们通过时序图确实发现创建SqlSessionFactory十分复杂,要解析大量的配置之后才能创建,因此我们实现了FactoryBean接口:
在这里插入图片描述
在getObject里面选择性的进行初始化并返回SqlSessionFactory对象。
至于获取SqlSessionFactorybean实例的时候,是怎么走到FactoryBean的getObject的方法的,可以参考AbstractBeanFactory.getBean方法,这属于spring ioc范畴了,这个需要很长的篇幅才能讲清楚,有机会我会单独写一篇spring怎么创建bean和获取bean的。

3 验证demo

如果你有demo的话,可以单步跟踪。如果没有的话,可以使用作者之前做过的一个基于layui的通用后台系统,简单的安装mysql和客户端之后(本地安装mysql和客户端真的很简单30分钟搞定吧)、稍微改下配置就可以直接运行这个项目(这个项目麻雀虽小,但五脏俱全,如果觉得好用,可以帮忙点个start)。

验证之前,我们先做个猜想:SqlSessionFactory是在afterPropertiesSet里初始化的还是在getObject里判断为空再初始化的?

我们分别在SqlSessionFactoryBean的afterPropertiesSet和getObject打上断点,然后debug项目,如下所示:
在这里插入图片描述
可以看到,在SqlSessionFactoryBean实例创建后,在afterPropertiesSet对SqlSessionFactory进行了初始化和创建。然后在获取它的时候,走的是getObject方法(这时候sqlSessionFactory已经不为空了):
在这里插入图片描述

4 举一反三

4.1 插件的配置是在SqlSessionFactoryBean的定义里面还是configuration的xml结点下面?

demo里的插件我们是写在mybatis-config.xml里面的configuration结点里面的,如下所示:
在这里插入图片描述
这是通用的做法,当然你也可以经常看到有人配置在SqlSessionFactoryBean的定义里面,如下所示:
在这里插入图片描述
那么问题来了,这两个有什么区别吗?
这个比较简单,作者自问自答一下。
这两个都可以作为插件的配置方式,都会起作用,因为在buildSqlSessionFactory过程中,如果发现插件不为空,就会添加到插件集合里面去,如下所示:
在这里插入图片描述
然后再解析xml时,又会将configuration的配置解析一遍,里面也包含插件的解析过程:
在这里插入图片描述
在这里插入图片描述
所以我们只需要在一个地方配置好就行了。然后它们有一个细微的差别,因为configuration是mybatis的配置,所以在configuration中的插件配置,是通过调用setProperties方法将属性传递进来,然后设置到插件的属性中。SqlSessionFactoryBean的插件配置不会调用setProperties方法,直接走的setter注入将属性注入进去。
在这里插入图片描述
这个大家也可以自行验证下。

4.2 mybatis的事务管理和spring的事务管理什么关系?

如果你仔细看了SqlSessionFactoryBean创建SqlSessionFactory的过程,那么肯定会注意到有这么一个调用:

if (this.transactionFactory == null) {
      this.transactionFactory = new SpringManagedTransactionFactory();
    }

因为我们配置的是spring的事务,在mybatis的配置文件里面没有为SqlSessionFactoryBean配置事务,如下所示:
在这里插入图片描述
所以那段代码里面transactionFactory会因为==null,而创建一个SpringManagedTransactionFactory,下面的截图也刚好印证了我们的观点。
在这里插入图片描述
那么问题来了,mybatis的事务和spring的事务是什么关系?它们是怎么配合的?
这个问题回答比较复杂,需要有spring事务的知识,大家可以尝试自己找答案,或者等作者后续的文章来解答。

5 总结

mybatis通过SqlSessionFactoryBean将SqlSessionFactory对象集成到spring中,它实现了InitializingBean接口,在SqlSessionFactoryBean初始化时解析配置并创建DefaultSqlSessionFactory对象。它还实现了FactoryBean,在getObject时返回我们创建好的DefaultSqlSessionFactory,使得DefaultSqlSessionFactory也被spring管理起来。
很多框架集成到spring的方法基本都是靠InitializingBean和FactoryBean这两个接口来实现的,这是一种非常好的设计,值得我们好好学习。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mybatis是如何集成到spring的之SqlSessionFactoryBean 的相关文章

随机推荐

  • 循环和数据的操作命令

    while循环的本质就是让计算机在满足某一条件的前提下去重复做同一件事情 即while循环为条件循环 包含 1 条件计数循环 2条件无限循环 1 1计数循环 count 0 while count lt 9 print the loop i
  • Vue前端框架

    一 简介 Vue是一个渐进式 真正用到才引用 的JavaScript框架与其它大型框架不同的是 Vue 被设计为可以自底向上逐层应用 Vue 的核心库只关注视图层 不仅易于上手 还便于与第三方库或既有项目整合 另一方面 与现代化的工具以及各
  • Android相机调用-CameraX【外接摄像头】【USB摄像头】

    Android相机调用有原生的Camera和Camera2 我觉得调用代码都太复杂了 CameraX调用代码简洁很多 说明文档 https developer android com jetpack androidx releases ca
  • 一文弄懂c/c++编译过程(预处理,编译,汇编,链接)

    目录 1 为什么要编译 2 编译过程 3 实验验证 1 为什么要编译 c语言是一门高级语言 需要编译器将其转换成计算机能理解的机器语言 才能在计算机上执行 编译的过程就是将c语言代码转换成汇编代码文件的过程 2 编译过程 程序从代码编译成可
  • 关于时间序列分析的协整检验、脉冲响应图、方差分解图和格兰杰因果检验

    1 关于时间序列中分的析过程 step1 单位根检验 一般来说 时间序列进行分析之前应该先检验是否存在单位根 如是 则需要进行差分转换 否则可以直接进行var vector autoregression 这里不讨论arma Autoregr
  • 【mysql】mysql启动关闭命令以及一些报错解决问题

    mysql启动关闭命令以及一些报错解决问题 1 利用cmd窗口启动mysql出现服务名无效 2 启动mysql出现发生系统错误 5 1 利用cmd窗口启动mysql出现服务名无效 利用net start mysql启动mysql报错 服务名
  • Vue如何实现权限管理

    一 权限管理 权限管理就是让不同的用户只能访问自己权限内的资源 有以下几种 路由权限 用户登录后只能看到自己权限内的导航菜单 且只能访问自己权限内的路由地址 视图权限 用户只能看到自己权限内的内容和按钮 请求权限 越权请求将其拦截 二 控制
  • 云原生之使用Docker部署h5ai文件展示页

    云原生之使用Docker部署h5ai文件展示页 一 h5ai介绍 二 检查本地docker服务 1 检查系统docker状态 2 检查docker版本 三 下载h5ai镜像 四 部署h5ai服务 1 创建数据挂载目录 2 创建h5ai容器
  • ajax中XMLHttpRequest对象详解

    ajax中XMLHttpRequest对象详解 ajax技术的核心或者说负责ajax进行同步或者异步服务器请求是XMLHttpRequest对象 在用使用ajax技术时 其实就是操作XMLHttpRequest进行相应的业务 方法 1创建X
  • Mybatis item 和 index 区别

    Mybatis item 和 index 区别 相信很多人多看过Mybatis官方文档 但是在文档中并没有详细的说明index 的详细讲解 这里废话不多说 直接上代码来分析它和item 的区别
  • vue项目运行报错:error ‘v-model‘ directives require no argument vue/valid-v-model

    在vue项目中 需要引用第三方库 比如vant 2 12 47 在使用Dialog弹出框组件 需要使用v model show来确定是否显示弹窗 在项目运行时 会报错 error v model directives require no
  • 游戏服务器显示异常什么意思,游戏服务器状态异常怎么解决办法

    游戏服务器状态异常怎么解决办法 内容精选 换一换 GAUSS 00701 cannot rename inherited constraint s SQLSTATE 42P16错误原因 修改继承的约束名 解决办法 禁止修改继承的约束名 GA
  • gaussdb mysql对比_GaussDB(for MySQL)

    GaussDB for MySQL 是华为自研的最新一代高性能企业级分布式数据库 完全兼容MySQL 基于华为最新一代DFV分布式存储 采用计算存储分离架构 最高支持128TB的海量存储 可实现超百万级QPS吞吐 支持跨AZ部署 数据0丢失
  • Macronix MX25L25645G NOR Flash无法擦除问题分析

    1 问题现象描述 处理器使用的 SAM9X60 使用的内核版本是 5 10 80 在调试 Macronix MX25L25645G NOR Flash时 发现flash驱动加载成功后 使用 mtd debug 工具 erase flash时
  • Python期末考试答案

    文章目录 一 选择题 和 的区别 列表的操作 字典 字符串 运算 类的继承 程序阅读题 二 判断题 三 简答题 在python中 递归函数的特性是什么 阐释python是什么样的一门编程语言及应用场景 阐述类的三大特性是什么 你是如何理解的
  • 用Python的pandas读取excel文件中的数据

    一 前言 hello呀 各位铁子们大家好呀 今天呢来和大家聊一聊用Python的pandas读取excel文件中的数据 二 读取Excel文件 使用pandas的read excel 方法 可通过文件路径直接读取 注意到 在一个excel文
  • PyQt5 按钮Button 添加事件(信号/槽)

    本文基于PyQt5 按钮Buttons样式设计 针对按钮添加响应的点击事件触发 效果截图 PyQt 模型设计 PyQt 设计器截图 UI 源码
  • 乘积怎么表示_三个连续自然数的和等于它们的乘积,求这三个数

    咋一看题目 还是不难 结果全班45人 只有2人写出解答过程 什么题 答案都能凑得出来 写不了过程 我们一起来看看这道五年级数学题 若a b c为三个连续自然数 且满足a b c abc 这三个自然数分别是多少 请写出解题过程 分析 这道题目
  • 7-3 打印沙漏

    7 3 打印沙漏 本题要求你写个程序把给定的符号打印成沙漏的形状 例如给定17个 要求按下列格式打印 所谓 沙漏形状 是指每行输出奇数个符号 各行符号中心对齐 相邻两行符号数差2 符号数先从大到小顺序递减到1 再从小到大顺序递增 首尾符号数
  • mybatis是如何集成到spring的之SqlSessionFactoryBean

    文章目录 1 前言 1 1 集成spring前使用mybatis的方式 1 2 集成mybatis到spring的关键步骤 2 SqlSessionFactoryBean对象分析 2 1 buildSqlSessionFactory做了什么