MyBatis运行原理SQLSessionFactory的初始化
一、前言
在前面的章节中,我们简单的介绍了一下MyBatis是如何配置使用的,为了更深切的体会到MyBatis的精髓,这一节我们将通过代码简单的看一看MyBatis的源码,分析一下MyBatis的执行流程
二、案例
修改MyBatisTest文件
在32行处,打上断点,运行,方法进入,读取全局配置文件,通过文件流的形式
进入文件流的源码就不看了,直接到new SqlSessionFactoryBuilder().build(inputStream)处
点击F5,进入下一步
点击F5,进入下一步进入SqlSessionFactoryBuilder的build方法
这时候我们发现在build方法里面创建了一个XMLConfigBuilder的parser对象,用来解析传入的文件流
下面我们看一下这个parser解析器做了什么操作,F5进入下一步,进入XMLConfigBuilder类的parse方法
上述方法,我们看到parser先去解析configuration这个根节点,然后将解析的结果交给parseConfiguration方法处理,我们可以看看parser.evalNode(“/configuration”)这个方法解析出来到底是什么东西?
大家有没有觉得很熟悉,这一段正好是我们mybatis-config.xml全局配置文件的内容,binggo,这段代码的作用就是去读取配置文件的信息。
下面我们进入parseConfiguration方法,看看它是怎么处理这些解析数据的?
可以看出来,它会一个一个的解析配置文件中的每一个节点,包括properties,typeAliases别名等。这些节点就是你在写配置文件时候用到的节点名称,它不会是别的名称,都是按照标准规范来的
接下来,我们随便找一个标签,看它是如何解析封装每个标签中的数据的,在103行打上断点
进入该方法
在这段方法里面,我们看到会将解析每一个标签的内容封装到configuration对象里面,像缓存cacheEnabled,懒加载lazyLoadingEnabled等。
接下来,我们退出该方法,进入到107行mapperElement(root.evalNode(“mappers”));断点处
这一段方法,很明显是解析mapper映射文件的方法
点击F5,进入该方法
读这段代码,如果是以package标签引入的,就走package那一段,现在我们的demo中是以mapper方式引入的,所以会走下面String resource = child.getStringAttribute(“resource”);这一段
如果你是以resource的方式引入的mapper,这里的resource就会有值,很明显我们在demo中是以resource这种方式引入的,你可以修改引入方式,这里获取的方式就会不一样。
下面这几段代码,对引入方式做了判断
最后一句还说明了,如果配置重复了会报错:A mapper element may only specify a url, resource or class, but not more than one.一个mapper只能有一个引入方式。
下面进入321行代码处
我们要开始解析EmpMapper.xml文件,大家有木有发现,MyBatis解析什么文件都是用一个解析器,这里解析SQL映射文件使用了mapperParser解析器
mapperParser长什么样子呢?
是一个XMLMapperBuilder对象,用的是XPathParser解析器,专门用来解析XML文件的下面我们看一下它是怎么解析Mapper文件的,断点,进入parse方法
然后parser开始解析根节点mapper,将解析的内容返回交给configurationElement方法处理parser.evalNode(“/mapper”)解析返回的结果如下:
很明显,这就是EmpMapper.xml文件的内容
断点,进入configurationElement方法
这里面主要对EmpMapper.xml文件中,每一个标签进行解析,正如代码所写的那样,如果你写了缓存,就回去解析缓存,如果写了ResultMap就会去解析ResultMap,如果学了增删改查就会去解析在增删改查这一段等.
下面我们以解析select|insert|update|delete增删改查标签为例,看看它是如何处理的?
在118行处,打上断点,进入该断点方法
如上,在最开始解析全局配置文件的配置在这里做了判断,问是否配置了DatabaseId属性,很显然我们的demo中没有配置,直接跳过
F5进入buildStatementFromContext(list, null)方法
这里面,我们又看到了一个新的解析器statementParser,用来解析节点,主要是解析这些SQL语句
断点,进入parseStatementNode方法
在这里面,我们可以看到,它会拿到该标签上所有能够写的属性的值,它会将这些获得的所有属性,添加到一个叫做addMappedStatement的方法,如图:
断点到107行,进入该方法,该方法最终返回的是一个MappedStatement中,所有增删改查的详细信息都是保存在这个MappedStatement方法中
接下来我们看看这个statement长什么样子?
基本上包含了,整个增删改查的所有详细信息,它代表的是一个增删改查的详细信息
跳出该方法,最后跳转到如下图:
我们发现不管怎样,最后解析处理的结果都会放到configuration中,这个configuration包含了所有配置文件解析的信息
接下来,继续返回
parser.parse()方法返回的configuration,封装到了build方法,那么build方法又做了什么呢?
继续断点
可以看到,最后configuration封装到了SqlSessionFactory中,返回了一个DefaultSqlSessionFactory对象。
一个简单的序列图如下:
从上我们可以得出结论关于SQLSessionFactory的初始化:把配置文件的信息解析并保存到configuration对象中,返回包含了configuration的DefauluSQLSession对象。这就是我们运行流程的第一步SQLSessionFactory的初始化。
=======欢迎大家拍砖,小手一抖,多多点赞哟!=======
版权声明:本文为博主原创文章,允许转载,但转载必须标明出处。