美文网首页
MyBatis印象阅读之起航篇

MyBatis印象阅读之起航篇

作者: 向光奔跑_ | 来源:发表于2019-07-19 11:02 被阅读0次

本篇开始分析关于MyBatis的使用和源码分析

1.MyBatis是如何运行的

这里我推荐直接进入官网上看Demo 官网入门Demo,为什么?
之前个人也没有习惯看官网,都是习惯直接百度谷歌搜索别人写的教程,这有什么缺点呢?

  • 内容质量参差不齐,无法有效筛选,浪费时间
  • 每篇内容重复程度高,且大多可能都是官网拷贝
  • 没有看官网来的全面

当然如果官网的文档提供不足,那么可以另寻他路。

OK,言归正传,我们进入正题:

首先在pom文件中添加

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

然后通过加载XML文件资源:

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

这里我们先不需要在乎有没有这样一个资源文件,我们先抓住MyBatis是如何来进行解析资源的,也就是SqlSessionFactoryBuilder类。

2. SqlSessionFactoryBuilder源码分析

这个类就一个方法名,我们简单看下:


SqlSessionFactoryBuilder方法

可以看到目的就是为了构建出SqlSessionFactory,我们找一个通用的方法进行分析

2.1 SqlSessionFactoryBuilder#build源码分析

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


  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

我们看到这里又出现了一个XMLConfigBuilder,见名知意,猜想这个类就是解析XML资源文件的。

3.XMLConfigBuilder源码分析

我们在分析源码的时候,先看属性和构造方法,再来看相应的方法,那么这个类的属性和构造方法是:

public class XMLConfigBuilder extends BaseBuilder {

  private boolean parsed;
  private final XPathParser parser;
  private String environment;
  private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();

  private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    super(new Configuration());
    //日志输出相关
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
  }

我们了解下它的组成结构,这里我们看到他继承了BaseBuilder,并且内部属性有两个我们是不太熟悉的类:
1.XPathParser
2.ReflectorFactory
那么在我们的技术债上加上

技术债

  • XPathParser
  • ReflectorFactory

再来看继承类BaseBuilder的代码。

3.1 BaseBuilder源码分析

public abstract class BaseBuilder {

  /**
   * 全局资源配置
   */
  protected final Configuration configuration;
  /**
   * 类型别名注册器
   */
  protected final TypeAliasRegistry typeAliasRegistry;
  /**
   * 类型处理注册器
   */
  protected final TypeHandlerRegistry typeHandlerRegistry;

  public BaseBuilder(Configuration configuration) {
    this.configuration = configuration;
    this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
    this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
  }
}

重点:每个继承BaseBuilder类的方法都可以获取到Configuration、TypeAliasRegistry、TypeHandlerRegistry三个类

这里又欠下了3个类的技术债,我们补充上:

技术债

  • XPathParser
  • ReflectorFactory
  • Configuration
  • TypeAliasRegistry
  • TypeHandlerRegistry

这个类都是辅助方法,没有什么主逻辑方法,所以我们继续回到他的继承类XMLConfigBuilder,大家是否还记的在<2.1>中我们使用了XMLConfigBuilder的parse()方法

3.2 XMLConfigBuilder#parse源码解析

//XMLConfigBuilder
  private boolean parsed;
  private final XPathParser parser;
  private String environment;
  private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();

public Configuration parse() {
    //初始化默认为false,代表是否解析过
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
 }

这里涉及到了使用XPathParser解析资源文件下的某个标签,然后使用parseConfiguration方法解析

3.2.1 XMLConfigBuilder#parseConfiguration
private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      loadCustomLogImpl(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);
    }
  }

这里我们使用过MyBatis配置文件的就会有点熟悉了,这里的每个方法都是解析资源文件中的一个标签,这里避免大家有些遗漏,我在官网中MyBatis官网XML配置

xml配置
这块逻辑大家应该不难理解,就是根据XML标签去取资源文件配置内容。

4.今日总结

今天我们查看了官网使用MyBatis使用流程,并且对于解析XML文件的流程进行了一定的梳理。
进而输出:

技术债

  • XPathParser
  • ReflectorFactory
  • Configuration
  • TypeAliasRegistry
  • TypeHandlerRegistry

之后便是分析到XMLConfigBuilder根据标签进行分析这步。

相关文章

网友评论

      本文标题:MyBatis印象阅读之起航篇

      本文链接:https://www.haomeiwen.com/subject/ylzdlctx.html