问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

MyBatis 执行流程及源码解析

发布网友 发布时间:2024-09-29 06:47

我来回答

1个回答

热心网友 时间:2024-10-07 00:26

在日常工作中,我们广泛使用MyBatis作为数据持久层框架,然而,你是否真正了解MyBatis的执行流程?本文将从源码角度,带你深入解析MyBatis的工作原理。

首先,我们来看一个简单的例子:在Service中调用Mapper接口。在调用时,你是否意识到注入的是什么?通过调试,可以发现实际上注入的`studentMapper`是一个类型为`MapperProxy`的代理对象。接下来,我们将从MyBatis环境初始化开始,详细分析代理对象的生成过程。

一、配置`SqlSessionFactoryBean`时,都做了什么?在进行Spring与MyBatis整合时,我们通常使用XML或注解方式配置`SqlSessionFactoryBean`。以注解方式为例,让我们一起看看`SqlSessionFactoryBean`的实现关系。

在这个过程中,我们会发现Spring中两个非常重要的接口:`FactoryBean`和`InitializingBean`。`FactoryBean`是一个Spring中特殊的Bean,通过其`getObject()`方法返回对象实例。而`SqlSessionFactoryBean`的`getObject()`方法具体实现如下:它用于创建并返回一个`SqlSessionFactory`。在Spring与MyBatis集成环境下,我们使用`SqlSessionFactoryBean`充当`SqlSessionFactory`。

`InitializingBean`接口中只包含一个方法`afterPropertiesSet()`,所有实现了该接口的类在bean初始化之前都需调用此方法。在`getObject`方法中,若`SqlSessionFactory`为空,则会调用此方法创建`SqlSessionFactory`。

通过调用`SqlSessionFactoryBuilder`的`build`方法,最终返回一个`DefaultSqlSessionFactory`实例。这个实例中保存了一个非常重要的`Configuration`对象。

二、`@MapperScan`都做了什么?在注解配置MyBatis时,通过`@MapperScan`指定Mapper存放的包,就能自动实现接口的实现类。那么,它是如何实现的呢?

深入`@MapperScan`的源码,发现其内部还有一行非常重要的注解:`ImportBeanDefinitionRegistrar`接口,提供了`registerBeanDefinitions`方法,向用户暴露了`BeanDefinitionRegistry`,即允许用户手动创建`BeanDefinition`并使用该注册器将其注册到Spring容器中。

查看`MapperScannerRegistrar`方法`registerBeanDefinitions`中的核心代码,主要创建了一个Mapper扫描器,开启扫描。

`ClassPathMapperScanner`中的`doScan`方法进一步处理生成的mapper的bean定义。

进入`processBeanDefinitions`方法,注意其中的画框代码及上方的注释,先查看从`BeanDefinitionHolder`获取`BeanDefinition`时`beanClass`初始值,然后等待`setBeanClass`执行完毕。通过`definition.setBeanClass()`将原始`BeanClass`类型替换为`MapperFactoryBean`类型。至此,完成了Mapper接口加载定义阶段中关键的一步,这也是生成代理对象`MapperProxy`的关键所在。

三、MyBatis如何生成代理对象?让我们一起看看`MapperFactoryBean`的继承关系。`MapperFactoryBean`继承自`SqlSessionDaoSupport`类,实现了`InitializingBean`接口。因此,我们首先关注`afterPropertiesSet()`方法。

`DaoSupport`中最终调用`MapperFactoryBean`中的方法。首先通过获取`sqlSession`获得非常重要的配置类`Configuration`,接下来查看`addMapper`方法,最终调用的是`MapperRegistry`的`addMapper`方法。

在红框中的代码中,我们创建了`Mapper`的代理工厂对象(还不是`Mapper`的代理对象),并将其放入`knownMappers`这个Map中。至此,只简单初始化了`MapperProxyFactory`,将我们自己的`mapper`的类型传给了它,但还没有真正生成代理对象。

`MapperRegistry`在之后的`parse`方法中完成了XML文件的解析,将每一个SQL方法解析为一个`MappedStatement`对象,并添加到`Configuration`对象中。最后,`MapperFactoryBean`返回的是`MapperProxyFactory`实例,通过它实例化并返回了一个代理对象。

四、`MapperProxy`代理对象如何执行SQL语句?在`StudentServiceImpl`中的`query`方法中插入断点,你会发现实际执行的就是代理类`MapperProxy`中的`invoke()`方法。

作为代理类的`MapperProxy`同时实现了`InvocationHandler`接口,因此`invoke`方法是执行代理逻辑的关键。在这里,最终调用`MapperMethod`的`execute`方法实际执行SQL语句。

在该方法中,根据SQL语句执行类型,调用`sqlSession`对应的方法执行并将结果返回给用户。至此,MyBatis在Spring环境下完成了一次调用。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
猛禽点烟器在什么位置? 哪家公司的Burkert角座阀性价比更高? 腊肠炒青豆做法 香肠炒青豆的家常做法大全怎么做好吃 我想模仿一个淘宝大店铺'主要是因为他们销量很好,。我想生产他们的... 模仿别人淘宝店铺算侵权吗?侵权赔偿标准介绍 applexsmax突然黑屏 大雁气功当代传人 贷款担保合同签字担保人没有来是不是有效 当一个习惯养成的时候,是不是戒不掉了 一遍文章带你看懂:《MyBatis 源码分析》 蓝牙音箱&数码播放器播放音乐的时候屏幕显示时钟怎么调?我需要显示屏上... 怎么让QQ音乐在连接蓝牙音箱的同时自动播放? 国际标准书号特点 国际标准连续出版物编号国际刊号ISSN简介 刊号概述 刊号ISSN格式 公积金提取银行反回卡为激活怎么搞 windows7怎么安装罗技驱动 安装windows7时出现缺少驱动程序怎么办? windows7 usb/dvd工具招人质疑已暂停下载 昆明较大的茶叶批发市场有哪几个? 不到一个月的小猫拉稀带血、精神不好。急救!谢谢谢谢、帮帮我,谢谢! ...连鸡蛋黄也不吃,浑身无力,肚子瘪瘪,我该怎么办 我家的母猫最近突然浑身无力,没有精神了,怎么办 以前的北京叫什么 阿克苏楼板打孔多少钱一立方 博乐地面打孔公司 为什么长期单身真的会上瘾? 单身上瘾是真的嘛 怎么用老公的手机号绑定老婆的微信。 实名认证必须用身份证和手机号码吗 朋友办手机分期用的我的身份证,能取消吗 朋友要借我身份证办分期我不想借又不好意思拒绝我该怎么办怎么说... 工商注册:个人所得税手续费返还应计入其他业务收入还是营业外收入? potplayer怎么截图potplayer截图教程 potplayer怎么截图快截图键是什么? 【经开区公司注册】个人所得税手续费返还应计入其他业务收入还是营业外... potplayyer截图教程 退回手续费进什么收入 想要去除脸上的红血丝,该如何选择护肤品? 怎样淡化脸部红血丝 脸上有红血丝容易爆痘应该怎么护肤? 要怎样才可以让直男喜欢上你?!希望腐女同男支支招啊啊! 他是同志么,如果是我该怎么办 近年来,“全民直播”的热潮开始兴起,导致网络直播乱象产生原因有哪些... C#打地鼠关于计分的问题 Winform、C#中的一些问题 lol,死歌与锤石哪个值得入手? LOL我现在有6300金币大家觉得买什么好。我中意的是锤石。还有断头台...