likes
comments
collection
share

Mybatis流程分析(一):揭秘Mybatis对配置文件解析的全流程

作者站长头像
站长
· 阅读数 17

在过去的几周内,我们从SpringMVC的配置文件入手,逐步分析了SpringMVC内部对于一个http请求处理的全过程,感兴趣的小伙伴可前往专栏SpringMVC流程分析进行查看。

事实上,对于一个web应用而言,其除了处理http请求的处理之外,还需要完成的另一件任务就是同数据库进行交互。提到数据库交互,你脑海中可能会迅速浮现出CRUD这几个单词。虽然从某种角度来看,无论多么复杂的业务,其最终对于数据库的操作,都无法脱离上述的这几个操作。或许,你会觉得只要熟悉了这几行命令就能完成大部分应用的开发,但CRUD操作背后的故事真的会这样简单吗?我想答案应该是否定的。

事实上,你之所以有这样的想法,很大程度上来说得益于越来越多的orm框架的出现,从而使得对于数据库复杂的操作逻辑都由框架来帮助我们完成,从而降低了开发web应用的难度和门槛。

Mybaits作为当下流行的Orm框架自发布之初便受到了广大开发者的追捧。那Mybaits背后究竟为我们做了哪些工作,才使得我们对于数据库CRUD操作变得如此简单呢?

那么,在接下来这段时间内,我们将对Mybatis源码进行分析讲解,相信坚持看完本专栏你一定会对Mybatis有一种全新的认识。

听到源码解析可能你想到的作者肯定是全文长篇累牍的贴代码,然后再逐行进行分析。如果你有这样的想法,那可能会让你失望了。

本专栏在写作上面是会对代码内容进行有的放矢的删减,只会保留重要的逻辑以帮助读者更好的理解Mybaits的处理逻辑。所以可以放心食用。

此外,本专栏创作的初衷也从来不是为了逐行分析Mybatis源码,因为这样收益甚微。作者更希望能从一种全新的角度带你认识Mybatis框架,从而帮助读者梳理MyBatis的主干脉络,加深对于MyBatis认识和理解。

前言

往往藏着框架的主干逻辑。 在开始分析一个框架之前,我们先来看看Mybatis框架是如何使用的。因为一些框架的主干逻辑,往往就藏在框架的使用流程中。下面这张图详细的说明了使用Mybatis的所需要的步骤。

 Mybatis流程分析(一):揭秘Mybatis对配置文件解析的全流程

总的来说,如果要使用Mybatis完成对数据库操纵,我们需要准备Mybatis相关的配置文件。具体来看,如果要完成对数据库操作,则我们必须告知Mybatis框架,其所需要连接数据库的地址、端口、用户名、密码等信息。此外,还需要创建映射器接口并编写映射器 xml 文件。

Mybatis加载流程初探

当配置完使用的Mybatis所需的配置文件后,接下来要做其实就是将配置文件的内容告知给MyBatis框架,在此阶段,通常我们会编写如下的代码信息:

  //<1> 加载配置文件
  InputStream is = Resources.getResourceAsStream("mybatis.xml");
  //<2> 创建sessionFactory对象
  sessionFactory = new SqlSessionFactoryBuilder().build(is);
  //<3> 获取sqlSession对象信息
  SqlSession session = factoy.openSqlSession()
  //<4> 构建映射器的代理对象
  UserMapper mapper = session.getMapper(UserMapper.class);
  // .....调用相关方法信息

(注:这样做的前提是我们已经引入Mybatis所需的依赖信息)

相信大家接触Mybatis一定是从上述代码开始的。上述代码背后的逻辑如下:

  1. 通过工厂构造器构建一个SqlSessionFactory对象
  2. 通过SqlSessionFactory获取到一个sqlSession对象
  3. sqlSession中传入一个Mapper对象信息,同时获取到一个Mapper对象
  4. 获取Mapper对象的代理类,调用接口中的方法,从而执行相关sql语句

通过观察上述代码,我们发现在这一过程中的<1>,<2>处我们会将配置好的xml信息传入到Mybatis中。接下来,我们便从此处开始入手,看看在Mybatis对这些配置文件做了哪些操作。

资源文件加载处理

<1>处,会通过一句Resources.getResourceAsStream("mybatis.xml")来获取一个输入流 对象。接下来,我们便进入到其内部看看ResourcesgetResourceAsStream究竟做了完成了哪些工作。

 public static InputStream getResourceAsStream(ClassLoader loader, 
                             String resource) throws IOException {
    InputStream in = classLoaderWrapper.
                       getResourceAsStream(resource, loader);
    return in;
  }

可以看到,此处只是一句平平无奇的资源加载,并没太多复杂处理逻辑。具体来看, 其会通过类加载器的getResourceAsStream方法返回一个输入流对象。

接下来,我们将目光转向<2>处,看看SqlSessionFactoryBuilder中又完成了哪些处理逻辑。其相关逻辑如下:

  public SqlSessionFactory build(Reader reader, String environment,   Properties properties) {
    // 构建XMLConfigBuilder对象
    XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
    return build(parser.parse());
    // ....省略无关代码
  }

可以看到,在<2>处调用的build方法内部,其首先会创建一个XMLConfigBuilder对象,然后再调用其的parse方法。

配置文件的解析的工具——XMLConfigBuilder

或许你对MLConfigBuilder这个类很陌生,不清楚其功能是什么。但不要慌,在分析之该类之前,我们不妨先来进行一个总结,看看如果要使用Mybatis究竟要做那些工作。具体来说,如果要正常使用Mybatis我们通常需要进行如下两步:

  1. 配置Mybatis所需的配置文件信息
  2. 加载配置文件信息,解析配置文件,构建接口代理对象

那这个MLConfigBuilder出现在第几步呢?很明显,它出现第二步中的配置文件解析过程中。如果此时你仍不清楚其功能。别着急,我们再继续接着往下看。我们注意到,在build方法中,会构建一个XMLConfigBuilder对象,并将配置文件的输入流传入。

至此,相信现在你现在大概率已经可以猜出来了这个XMLConfigBuilder的作用大概率是完成对xml配置文件的解析。

为了验证这样这一猜想,我们不妨进入到其调用的parse方法,看看其究竟完成了那些操作。

public Configuration parse() {
    // 解析Configuration标签下的内容
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
}

private void parseConfiguration(XNode root) { 
  // 解析configuraion标签下的properties标签
  propertiesElement(root.evalNode("properties"));
  // 解析configuraion标签下的environments标签
  environmentsElement(root.evalNode("environments"));
  // ...省略其他无关代码
}

可以看到,在parse方法中,其会调用parseConfigurationconfiguration标签的内容。

(注:此处的逻辑主要就是对xml节点的解析操作,具体细节不再展开详细介绍)

总结

至此,我们便分析清楚了MyBatis对于配置文件的解析全过程。整体细节如下图所示:

 Mybatis流程分析(一):揭秘Mybatis对配置文件解析的全流程

事实上,对于Mybatis的加载过程来说,其在处理配置文件信息时,首先,会传递配置文件所在位置信息,然后再调用框架提供的SqlSessionFactorybuild方法便会根据传入路径信息去加载相关的配置文件,并进行解析。而解析的内容会存放到的configuration之中,进而方便后续组件的使用。

(注:对于图中的ConfigurationSqlSessionFactory的内容,则会在下一章进行介绍和分析。)

转载自:https://juejin.cn/post/7267106802649563170
评论
请登录