【MyBtais源码阅读】(二)探究Configuration 1

        在上一篇【MyBtais源码阅读】(一)从头开始 中我们提到了几个重要的对象,今天我们带着之前的疑问来探究一下Configuration这个对象。这个对象是贯穿了整个mybatis,到处可以看见它的身影。

        String resource = "mybatis-config.xml";
        //加载mybatis核心配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //构建sqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //获取sqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //执行查询数据库
        Job job = (Job)sqlSession.selectOne("org.example.dao.JobMapper.selectJob", 3);
        System.out.println(job.toString());

       这段代码很熟悉吧,对的,就是测试例子中的测试代码,用来查询数据库job表中的一条数据,但是在这整个测试代码中都没有看到Configuration,这又是怎么回事呢?我们仔细看来,代码中有一行是在加载核心配置文件成为一个InputStream,莫非这个核心配置文件就是我们需要的Configuration,但是此处加载仅仅只是把它作为一个流传入后面的构建sqlSessionFactory里面了,并没有看到我们想要的类似 new Configuration();这样的代码存在呢?于是我们带着疑问,逐步进入后面的代码。。。

        没错, 我们正打算阅读的代码就是 SqlSessionFactoryBuilder,因为我们加载的配置文件以流的形式传入了build() 方法,因此,我们要探究Configuration,就必须要探究这个类。

我们细读这个类里面的属性和方法,发现这个类没有属性,只有一大堆的重载build方法。因此我们只能探究这个调用的build()方法了

   //代码1
   //上述代码调用的,指传入一个inputStream的build方法
  public SqlSessionFactory build(InputStream inputStream) {
    //此处调用重载的另一个build方法,只不过除了inputStream,默认值都是null
    return build(inputStream, null, null);
  }


  //代码2
  //上述代码调用的方法
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //从传入的inputStream(因为剩下两个参数都是null)构建一个XMLConfigBuilder
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //调用重载的build方法返回一个SqlSessionFactory 
      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.
      }
    }
  }


  //代码3
  //上述代码调用的方法
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

我们发现,在上述代码中,通过代码1调用代码2再调用代码3的过程中。我们发现在代码3的入参看到了我们需要的Configuration,于是我们仔细阅读发现是代码2里面的parser.parse() 方法返回的。因此我们可以确定,Configuration就是通过XMLConfigBuilder 里面的parse()方法构建完成的。因此我们需要进一步了解构建Configuration这个对象的XMLConfigBuilder。

XMLConfigBuilder结构如下

XMLConfigBuilder继承关系如下(仅仅只继承了BaseBuilder)

BaseBuilder 结构如下

我们通过阅读上述代码的源码和继承关系发现, XMLConfigBuilder只继承于BaseBuilder,而且在BaseBuilder里面发现了我们需要的Configuration,于是我们关注回到上述的代码2

  //代码2
  //上述代码调用的方法
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //从传入的inputStream(因为剩下两个参数都是null)构建一个XMLConfigBuilder
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      ......
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ......
    }
  }

  //代码a
  public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
    this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
  }

  //代码b
  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;
  }

我们进入代码2, 携带三个参数的XMLConfigBuilder的构造函数代码a,其内部调用了私有的构造函数代码b,就在此时,我们发现了在代码b中,我们找到了我们需要的代码new Configuration(),它作为参数传入的BaseBuilder的构造函数,经过初步的探寻,我们终于找到了Configuration是在哪里创建的。但是仅仅找到是在哪里创建的就结束了吗?我的好奇心促使我想进一步的了解,在代码a中new XPathParser() 和 XMLMapperEntityResolver(),以及整个Configuration是做什么的。

总结:

        1:经过上述代码探究,我们初步了解了Configuration是在XMLConfigBuilder中创建的

        2:Configuration是作为BaseBuilder的一个属性储存了下来

上一篇 下一篇

【个人阅读源码,能力有限,望各方大佬有幸瞧见后能指点一二,如果有错误之处,我看到后会立马改正,谢谢🙏🙏🙏】

阿里云服务器优惠卷

阿里云优惠卷

阿里云新用户优惠

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值