mybatis系统学习(五)——mybatis源码之内部基本处理流程

mybatis使用中的模块交互

在之前的学习中我们知道了,一个简单的基础mybatis项目基本会包含如下几个必要的部分:
这里写图片描述
从上图中可以清晰的看到,整个数据的走向最终是指向了业务类,也就是说无论是配置还是接口,还是依赖包,最终的作用都是为了业务,为了解决实际问题。
同时,mybatis.xml配置文件和业务类,以及mapper.xml映射文件都需要依赖包的支持,因为里边的类或者标签需要用到mybatis封装的类。
之后,mapper.xml映射文件也指向了mybatis.xml,意思是在mybatis.xml文件中需要指定映射文件,否则相应的mapper映射便没有被引用,也就无效。
而之后的数据实体类和数据操作接口又都指向了mapper.xml,意思是mapper里的配置就是数据和接口的整合,从而成为具体的实现。

上边整理的图中各模块内容的交互,我觉得可以看成是实际开发项目中需要我们自己处理的内容交互,这些基本都还是处理用的阶段。
那么接下来要说的,就是mybatis内部的实现,看一看mybatis里边是如何整合和运行的。

mybatis运行时内部流程

程序运行,首先会进入程序入口,我们之前的例子中就是实际的业务处理类,也就是测试类,里边的主要代码回顾如下:

InputStream inputStream = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List list = userMapper.findUsers();

上边的代码没有分支,就是一个简单的顺序结构。顺序结构的程序运行时从上往下,但为了分析出运行过程中的关键点,我决定从下往上来看。

那么首先是最后一行,这里边要关注的点,很显然是变量userMapper,需要知道他是怎么被初始化赋值的;
往上看就会看到userMapper是从sqlSession中get出来的,那么很显然,userMapper应该在sqlSession中初始化的。
但是进一步分析就会发现SqlSession 是一个接口,那么这个初始化就应该是在他的子类中。
SqlSession子类是谁呢?以上的步骤无法确定,所以没办法就只能继续往上看。

这时候会看到SqlSession是从SqlSessionFactory 中拿到的,使用了SqlSessionFactory 的openSession方法。
但是再进一步分析会发现和SqlSession 一样,SqlSessionFactory也是一个接口,那么很显然需要继续确定SqlSessionFactory的运行中的子类。

然后就看到SqlSessionFactory是通过SqlSessionFactoryBuilder的build方法初始化的,就需要进入build看个究竟。
进入build之后,发现首先是根据传入的输入流创建了一个XMLConfigBuilder对象,在XMLConfigBuilder中给了configuration、parsed、environment、parser四个变量赋值。
之后继续调用重载的build方法返回了一个DefaultSqlSessionFactory,这个时候还调用了XMLConfigBuilder的parse方法,在parse方法中初始化了很多数据,其中就包括了解析mapper,这里先放下不提。
需要提的是,终于找到了第一确定的类:DefaultSqlSessionFactory。

既然这样,接下来就可以倒回去看,上边说SqlSession是从SqlSessionFactory 中拿到的,现在可以确定实际是从DefaultSqlSessionFactory中拿的,也就是使用了DefaultSqlSessionFactory的openSession方法。
在openSession中就会看到最后返回了一个DefaultSqlSession。

找到了SqlSession的具体子类,那么就能回到最初的问题,userMapper是如何被初始化的。
在DefaultSqlSession的getMapper方法中会看到,里边又调用了configuration的getMapper方法。
那么再进一步分析,userMapper实际应该是在configuration里边初始化的,再进入configuration的getMapper方法,会看到又调用了mapperRegistry的getMapper方法,最终发现是从mapperRegistry类的knownMappers变量中取出来的userMapper。

那么这时候需要解决的问题,就是userMapper是怎么被加入到knownMappers中的呢?
经过在Configuration查找,会发现有一个addMapper方法,正是这里边的处理,使得userMapper加入了knownMappers中。
那么这个addMapper又是什么时候调用的,在哪里调用的呢?回想一下上边会发现,在SqlSessionFactoryBuilder的build的时候,有一个parse步骤,里边解析了mapper,然后正好就是调用了Configuration的addMappers方法,最终调用addMapper方法。

那么到这里,整个mybatis运行时内部处理的基本脉络就相对清晰了,可以初步整理为如下图所示的流程:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/tuzongxun/article/details/80533044