对 在spring中使用Mybatis 的一些思考

使用spring mvc +Mybatis的已经很多年了,通常使用mybatis做为持久层,在spring使用mybatis只需要通过以下简单的四个步骤,就可以从数据库中获取数据。这四个步骤就是:1、定义实体bean ;2、定义mapper接口 ;3、在xml文件中写sql;4、在service中调用相应Mapper方法。突然有一天我的脑海中出现几个疑问:

  1. 接口是不能被实例化,那么在service中定义的mapper如何被实例化的。
  2. 我们写在xml中的sql语句,是如何和mapper接口中的方法相对应。换句话说,我们再调用接口方法,接口方法是如何执行到相对应的方法。
    要解开这两个问题,开代码最为直接。接下来就开始了,我苦逼的看源码的过程了。接下来依次解决这个两个问题的疑惑。

问题一: 接口是不能被实例化,那么在service中定义的mapper如何被实例化的

我们都知道接口是不能被实例化的,那么我们通常是需要些一个mapper的接口,同过spring的注解方法就直接可以在service类中使用,这个很奇怪。一定是spring容器在启动的时候对相应的mapper的接口做了手脚。那有了这个猜想我们就要同过源码去验证我的猜想。为了看spring在启动过程中对mybatis中mapper做了什么手脚,首先我们要创建一个spring boot+mybatis的项目,在相应的mysql中一个简单的表,在项目中创建对的bean,mapper,xml等相应的东西。启动项目,使用debug一步一步的跟踪spring启动的时候的代码突然有个东西映入我眼帘,“ClassPathMapperScanner“,好家伙,这是什么东东。仔细一看原来扫描mapper的工具类。打开ClassPathMapperScanner类,我看到入下方法:

image.png

其中第一个用红线框标出来的代码是用来扫描相应的mapper。那第二个红线框标出来的processBeanDefinitions(beanDefinitions);根据字面意思是处理扫描出来的mapper的吧。我们继续跟进代码,看下图:

image.png

看到图中用红线框标出的代码,很明显spring在启动的时候将相应的beanClass替换为this.mapperFactoryBeanClass。那么this.mapperFactoryBeanClass又是何方神圣,继续看代码,如图:

image.png

那我们继续看MapperFactoryBean到底有什么能耐,继续看源码:

image.png

原来MapperFactoryBean是一个FactoryBean用于生产Mapper想对应的实例。
原本事情到这里应该告一段落,可是为了能更好的和下一个问题有一个衔接。我们还要继续往下看。我们在MapperFactoryBean中找到getObject()方法:

image.png

我们通过getSqlSession().getMapper(this.mapperInterface);方法一直跟踪到MapperRegistry-->getMapper()方法:

image.png

我们在getMapper方法中看到mapperProxyFactory.newInstance(sqlSession);从字面意思中我们可以发现,这个方法应该使用动态代理生成mapper的对象。为了一探究竟,继续查看MapperProxyFactory源码。

image.png

的确,MapperProxyFactory是通过动态代理生成mapper对象。请注意我用红线框标记代码,MapperProxy是个InvocationHandler的实现类(大家都知道,动态代理少不了),这个行代码和我下一个问题仅仅相关的。欲知原由,且看下一问题的分解。

问题二:写在xml中的sql语句,是如何和mapper接口中的方法相对应

在spring-boot项目启动过程时,spring-boot会通过MybatisAutoConfiguration来初始化SqlSessionFactory。我们知道SqlSessionFactory是获取访问数据的session。那在创建SqlSessionFactory时Mybatis又做了什么?看下图:

image.png

从代码中我们看到,SqlSessionFactory 是由MybatisSqlSessionFactoryBean创建而来。那么在SqlSessionFactoryBean中是否有和我们提出的问题相关的内容吗。现在让我们打开SqlSessionFactoryBean的真面目。现在我们一起看下庐山真面目:

image.png

请注意我用红线框标出的代码,难道 MybatisXmlConfigBuilder 就是用来解析xml中的sql语句的吗? 我们把buildSqlSessionFactory方法拉到最后,我们看到如下代码:

image.png

最为重要的是xmlMapperBuilder.parse(),难道解析的细节就在这里面吗?我那激动的小心脏呀。。。。
继续跟进xmlMapperBuilder.parse()方法。

image.png

用红线框中的第三个方法,看字面意思就是处理sql语句的。继续跟进这个方法:

image.png

我们看到parseStatementNode()方法,这里面就是解析xml文件中的sql语句。一起看下图:

image.png

这里面就是真正处理xml中sql语句。
然而这还没有解答我们提出的问题,xml和mapper接口中的方法如何对应上的。那我们接着往下看代码。在
parseStatementNode()方法的最后我们看到入下代码:

image.png

我们打开addMappedStatement方法

image.png

通过这个方法,把xml的语句转换为MappedStatement对应,然后存入configuration中的map对象中,其中map的key,就是xml中的id属性。如下图所示:

image.png

然后我们再回到第一个问题的最后,我提的MapperProxy,他是InvocationHandler实现类。我们现在可以一睹他的真面目。

image.png

在这我就只截取他的invoke方法(知道动态代理的都知道)。我们继续跟进MapperMethod方法中execute方法。

image.png

我们注意用红线框的方法,打开该方法。

image.png

该方法的第一行,我们很清楚的看到了 MappedStatement。第二问题的最终答案也在于此!

(题外话:以前在网上看别人写的技术博客,总是感觉这么简单的东西,还要写。现在自己写东西了,平时感觉简单的东西,突然不会了写不出来了。现在看来不管好于坏能写出来都很不错!)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容