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

2023年 8月 15日 33.7k 0

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

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

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

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

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

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

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

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

前言

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

adc2158870bf525154230bffac0c5ba.png

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

Mybatis加载流程初探

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

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

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

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

  • 通过工厂构造器构建一个SqlSessionFactory对象
  • 通过SqlSessionFactory获取到一个sqlSession对象
  • sqlSession中传入一个Mapper对象信息,同时获取到一个Mapper对象
  • 获取Mapper对象的代理类,调用接口中的方法,从而执行相关sql语句
  • 通过观察上述代码,我们发现在这一过程中的处我们会将配置好的xml信息传入到Mybatis中。接下来,我们便从此处开始入手,看看在Mybatis对这些配置文件做了哪些操作。

    资源文件加载处理

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

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

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

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

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

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

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

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

  • 配置Mybatis所需的配置文件信息
  • 加载配置文件信息,解析配置文件,构建接口代理对象
  • 那这个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对于配置文件的解析全过程。整体细节如下图所示:

    image.png

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

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

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论