美文网首页
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