前言

在了解MyBatis架构以及核心内容分析后,我们可以研究MyBatis执行过程,包括

  • MyBatis初始化

  • SQL执行过程

而且在面试会问到一下关于MyBatis初始化的问题,比如:

  • Mybatis需要初始化哪些?

  • MyBatis初始化的过程?

MyBatis初始化

在 MyBatis 初始化过程中,会加载 mybatis-config.xml 配置文件、Mapper.xml映射配置文件以及 Mapper 接口中的注解信息,解析后的配置信息会形成相应的对象并保存到 Configuration 对象中。初始化过程可以分成三部分:

  • 解析mybatis-config.xml 配置文件

    • SqlSessionFactoryBuilder

    • XMLConfigBuilder

    • Configuration

  • 解析Mapper.xml映射配置文件

    • XMLMapperBuilder::parse()

    • XMLStatementBuilder::parseStatementNode()

    • XMLLanguageDriver

    • SqlSource

    • MappedStatement

  • 解析Mapper接口中的注解

    • MapperRegistry

    • MapperAnnotationBuilder::parse()

解析mybatis-config.xml 配置文件

MyBatis 的初始化流程的入口是 SqlSessionFactoryBuilder::build(Reader reader, String environment, Properties properties) 方法,看看具体流程图:

如何回怼面试官的MyBatis执行过程初始化执行问题_第1张图片


public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {    try {
     XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);      return build(parser.parse());
   } catch (Exception e) {      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
   } finally {
     ErrorContext.instance().reset();      try {
       inputStream.close();
     } catch (IOException e) {        // Intentionally ignore. Prefer previous error.
     }
   }
 }

首先会使用XMLConfigBuilder::parser()解析mybatis-config.xml 配置文件,

  • 先解析标签configuration内的数据封装成XNode,configuration 也是 MyBatis 中最重要的一个标签

  • 根据XNode解析mybatis-config.xml 配置文件的各个标签转变为各个对象

private void parseConfiguration(XNode root) {    try {      //issue #117 read properties first
     propertiesElement(root.evalNode("properties"));
     Properties settings = settingsAsProperties(root.evalNode("settings"));
     loadCustomVfs(settings);
     typeAliasesElement(root.evalNode("typeAliases"));
     pluginElement(root.evalNode("plugins"));
     objectFactoryElement(root.evalNode("objectFactory"));
     objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
     reflectorFactoryElement(root.evalNode("reflectorFactory"));
     settingsElement(settings);      // read it after objectFactory and objectWrapperFactory issue #631
     environmentsElement(root.evalNode("environments"));
     databaseIdProviderElement(root.evalNode("databaseIdProvider"));
     typeHandlerElement(root.evalNode("typeHandlers"));
     mapperElement(root.evalNode("mappers"));
   } catch (Exception e) {      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
   }
 }

再基于Configuration使用SqlSessionFactoryBuilder::build()生成DefaultSqlSessionFactory供给后续执行使用。

解析Mapper.xml映射配置文件

首先使用XMLMapperBuilder::parse()解析Mapper.xml,看看加载流程图来分析分析

如何回怼面试官的MyBatis执行过程初始化执行问题_第2张图片


通过XPathParser::evalNode将mapper标签中内容解析到XNode

public void parse() {   if (!this.configuration.isResourceLoaded(this.resource)) {       this.configurationElement(this.parser.evalNode("/mapper"));       this.configuration.addLoadedResource(this.resource);       this.bindMapperForNamespace();
 }   this.parsePendingResultMaps();   this.parsePendingCacheRefs();   this.parsePendingStatements();
}

再由configurationElement()方法去解析XNode中的各个标签:

  • namespace

  • parameterMap

  • resultMap

  • select|insert|update|delete

private void configurationElement(XNode context) {   try {     String namespace = context.getStringAttribute("namespace");     if (namespace == null || namespace.equals("")) {       throw new BuilderException("Mapper's namespace cannot be empty");
   }
    builderAssistant.setCurrentNamespace(namespace);
    cacheRefElement(context.evalNode("cache-ref"));
    cacheElement(context.evalNode("cache"));
    parameterMapElement(context.evalNodes("/mapper/parameterMap"));
    resultMapElements(context.evalNodes("/mapper/resultMap"));
    sqlElement(context.evalNodes("/mapper/sql"));     //解析MapperState
    buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
 } catch (Exception e) {     throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
 }
}

其中,基于XMLMapperBuilder::buildStatementFromContext(),遍历