mybatis是如何集成到spring的之SqlSessionFactoryBean

news/2024/10/23 7:17:55/

文章目录

  • 1 前言
    • 1.1 集成spring前使用mybatis的方式
    • 1.2 集成mybatis到spring的关键步骤
  • 2 SqlSessionFactoryBean对象分析
    • 2.1 buildSqlSessionFactory做了什么事情?
    • 2.2 为什么是SqlSessionFactoryBean却可以使用SqlSessionFactory?
  • 3 验证demo
  • 4 举一反三
    • 4.1 插件的配置是在SqlSessionFactoryBean的定义里面还是configuration的xml结点下面?
    • 4.2 mybatis的事务管理和spring的事务管理什么关系?
  • 5 总结

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这两个接口来实现的,这是一种非常好的设计,值得我们好好学习。


http://www.ppmy.cn/news/165071.html

相关文章

Unity面试题:热更新篇(一)

请简要介绍Unity热更新的原理和实现方式。 答&#xff1a;Unity热更新的原理是通过将游戏的资源和代码分离&#xff0c;将代码部分放置在服务器端&#xff0c;游戏启动时通过网络下载更新的代码并动态加载&#xff0c;以达到实现热更新的目的。实现方式包括AssetBundle、ILRunt…

电脑录视频用什么软件最好?录像软件,3大工具推荐!

案例&#xff1a;电脑屏幕录像软件哪个好用&#xff1f; 【电脑录像工具是我工作必不可缺少的工具&#xff0c;我现在使用的录屏工具性能不太好&#xff0c;很大程度上影响到我的工作效率。我想找一款好用的录屏软件。】 在现代社会中&#xff0c;越来越多的人有电脑录制视频…

记一次 String(-0) 引起的 bug

-0 在js中是存在的&#xff0c;可以通过 var a -0 得到&#xff0c;也可以通过 parseInt(-0.1) 得到 但是存在 -0 0, String(-0) String(0) 的情况 起初&#xff0c;业务中存在一个 给数字转换成 千分位数字字符串的方法 // numInt 为传入的值, 如 1035 let integer pars…

I420转NV21

//I420 To NV21 void I420ToNV21(u8 *pSrcData, u16 wWidth, u16 wHeight, u8 *pDstData[]) {u64 dwSize wWidth * wHeight, i, j;u8 *pSrcData_U pSrcData dwSize;u8 *pSrcData_V pSrcData dwSize (dwSize >> 2);memcpy(pDstData[0], pSrcData, dwSize);//y分量fo…

DELL U2410显示器发红的解决方案

很简单, 换成DVI线连接. 不要用display port

TQ2440 USB驱动

TQ2440 USB驱动是官方提供的一款USB驱动&#xff0c;本站收集提供高速下载&#xff0c;用于解决USB接口不能正常识别&#xff0c;无法正常使用的问题&#xff0c;本动适用于&#xff1a;Windows XP / Windows 7 / Windows 8 / Windows 10 32/64位操作系统。有需要的朋友可以来本…

dvi黑屏解决方法_DVI线导致黑屏故障处理全攻略

笔记本如果遇到黑屏花屏的现象&#xff0c;相信朋友们都会想着把笔记本交给商家去维修&#xff0c;如果尚在保修期还好&#xff0c;过保了问题就大了。笔记本属于精度很高的产品&#xff0c;硬件损坏之后的更换是相当昂贵的。特别是主板损坏&#xff0c;商家的报价大约是2000-3…

dvi黑屏解决方法_DVI线导致黑屏故障处理全攻略分享

今天来聊聊一篇关于DVI线导致黑屏故障处理全攻略分享的文章,现在就为大家来简单介绍下DVI线导致黑屏故障处理全攻略分享,希望对各位小伙伴们有所帮助。 电脑黑屏是一个很常见的故障&#xff0c;引起这个故障的原因也是多种的&#xff0c;但是其中的一个原因是因DVI线导致显示器…