连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

2年前 (2022) 程序员胖胖胖虎阿
288 0 0

两天前,舍友大方去面试了一家小公司

面试官:看你的简历上写着 ”熟练使用MyBatis“,你对 MyBatis 很了解咯

大方:是的,我能熟练使用 MyBatis 的增删查改,以及动态查询

面试官:那你看过 MyBatis 的底层源码吗?

大方:啊,这个我没有看过诶…

面试官:没事,你回去等通知吧

那如何简洁地回答 MyBatis 的源码呢?

相信大家对 MyBatis 的构建流程已经很熟悉了吧!

public static void init() throws IOException {
    // 加载MyBatis.xml文件
    in = Resources.getResourceAsStream("classpath:MyBatis-Config.xml");
    // 通过SqlSessionFactoryBuilder的build方法加载输入流,构建SqlSessionFactory
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(in);
    // 执行OpenSession方法
    session = factory.openSession();
    // 调用getMapper获取mapper接口类
    videoMapper = session.getMapper(VideoMapper.class);
}

顺着这个流程,我们简单讲一下底层原理

getResourceAsStream() 是一个加载文件并转化为输入流的方法,这个就不需要多说了。

重点放在这个build方法,我们看看build方法中写了什么

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      // 通过 Xml解析器解析mybatis.xml文件,并调用parse方法
    return build(parser.parse());
  } catch (Exception e) {
  } finally {
    try {
      inputStream.close();
    } catch (IOException e) {
    }
  }
}

这个parse就是核心解析方法了,他xml文件中每个节点进行解析,解析并将数据加载到框架中

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

看他加载了这么多节点,一开始他解析最大的父节点《configuration》,解析出多种子节点并对子节点接着解析。

我们重点看这两个节点的解析,一个是environment节点的解析,解析完成后加载mybatis环境

private void environmentsElement(XNode context) throws Exception {
  if (context != null) {
    if (environment == null) {
      environment = context.getStringAttribute("default");
    }
    for (XNode child : context.getChildren()) {
      String id = child.getStringAttribute("id");
      if (isSpecifiedEnvironment(id)) {
        TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          // 获取数据源,我们已经编写好的url、driver、username、password
        DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
        DataSource dataSource = dsFactory.getDataSource();
          // 通过构建器模式构建出环境,并设置到configuration中
        Environment.Builder environmentBuilder = new Environment.Builder(id)
            .transactionFactory(txFactory)
            .dataSource(dataSource);
        configuration.setEnvironment(environmentBuilder.build());
      }
    }
  }
}

上面这一步设置环境是重点中的重点,有了上面这一步,mybatis才能正常启动起来

另外一个节点就是mapper节点,官网上写着mapper的几种实现方式:package、resource、url、class,这里就不详细介绍,这里是通过节点属性解析之后,获取mapper.xml的加载方式,最终解析并

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

最终,我们会进入这个方法

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

这个方法就是加载mapper.xml文件中sql语句的方法,加载完sql语句后,存放在mappedStatement中

至此,build构建方法加载完毕,接下来就是OpenSession方法

其实这个方法也很简单,重点就是这个 newTransaction 方法,他封装了 JDBC 底层的代码

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

诺!这些方法是不是很熟悉

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

有了 jdbc 的方法后,接下来就是 sql 语句的执行了

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

继续点击底层查看代码,在点击 MapperProxyFactory 这个类的时候,我们发现,mybatis 通过代理模式,动态地创建mapper

我们点击 MapperProxy 进入查看

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

在这个方法中,我们突然发现 MapperMethod 最后调用了 execute 解析方法!我们点进去查看一下这个解析方法实现了什么

连小公司都开始问MyBatis底层源码了?如何简练回答面试官MyBatis底层原理?

哇哦!增删查改都写在这里了,四种类型的数据库操作方法,也同时对应封装好了返回结果

mybatis 的原理流程大概就是这样子过了一遍,当然,这不是全部,有很多我们没有深入的地方如XNode节点、缓存等等,有兴趣可以一起讨论。

哎呀!好像讲到这里有点乱,我来总结一下整个流程吧!

一开始,我们需要跟面试官说明一下,什么是 ORM 框架,实际上很多同学知道 ORM 框架有 MyBatis、Hibernate、Jpa等,但是并不能说明白 ORM 框架是什么?

ORM 框架就是将 Java 中的对象实体,与数据库表关联起来并一一对应的框架。比如,将 user 表和 User pojo 绑定在一起,将数据库中的 varchar 与 Java 中的 String 对应起来,

  • 首先,调用 Resources.getResourceAsStream() 方法加载 MyBatis-Config.xml 文件
  • 接着,通过 build() 方法加载输入流
  • 通过 XmlConfigBuilder 执行 parse() 对xml 文件中的节点进行解析
  • 在 parse 解析中,最重要解析的两个节点,分别是 environments 和 mappers
  • 解析 environments ,并将其放到 configuration 中
  • 解析 mappers,并将它们放到 kownmapper 中
  • 接着执行 OpenSession 方法,这个方法封装了 jdbc 底层的数据库操作方法
  • 通过 getMapper 方法,调用我们需要的 mapper 接口
  • 并通过 jdk 的动态代理,为我们代理了 MapperMethod 类
  • 调用 excute() 方法,我们发现这里已经写好了增删查改的方法,最终返回mybatis为我们封装好的result结果集

本文由mdnice多平台发布

相关文章

暂无评论

暂无评论...