Mybatis构建SqlSessionFactory(2)2018-08-16

 今天我们来根据上一篇Mybatis(1)的案例我们来追追下源码:
我们从mybatis主要构件的执行流程:

mybatis.png

那么我们先来看看SqlSessionFactoryBuilder创建SqlSessionFacctory的过程:
这边我们SqlSessionFactoryBuilder这个类:

public class SqlSessionFactoryBuilder {
    public SqlSessionFactoryBuilder() {
    }
  //Reader读取mybatis配置文件
    public SqlSessionFactory build(Reader reader) {
        return this.build((Reader)reader, (String)null, (Properties)null);
    }
     //Reader读取mybatis配置文件
    //Environment决定加载哪种环境(开发环境/生产环境)
    public SqlSessionFactory build(Reader reader, String environment) {
        return this.build((Reader)reader, environment, (Properties)null);
    }
     //mybatis配置文件 + properties, mybatis配置文件中能使用${}形式
    public SqlSessionFactory build(Reader reader, Properties properties) {
        return this.build((Reader)reader, (String)null, properties);
    }
    //通过XMLConfigBuilder解析mybatis配置,然后创建SqlSessionFactory对象
    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();

            try {
                reader.close();
            } catch (IOException var13) {
                ;
            }

        }

        return var5;
    }
  //以下4个方法都只是Reader换成了InputStream
    public SqlSessionFactory build(InputStream inputStream) {
        return this.build((InputStream)inputStream, (String)null, (Properties)null);
    }

    public SqlSessionFactory build(InputStream inputStream, String environment) {
        return this.build((InputStream)inputStream, environment, (Properties)null);
    }

    public SqlSessionFactory build(InputStream inputStream, Properties properties) {
        return this.build((InputStream)inputStream, (String)null, properties);
    }

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();

            try {
                inputStream.close();
            } catch (IOException var13) {
                ;
            }

        }

        return var5;
    }
    //最后一个build方法使用了一个Configuration作为参数,并返回DefaultSqlSessionFactory
    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
    }
}

 从SqlSessionFactoryBuilder的代码我们可以总结出创建SqlSessionFactory的方式实际上是有两种:

1、不使用XML构建SqlSessionFactory :

实际上就是我们上一个篇张中使用的案例。就是使用Java程序而不是XML文件中直接创建配置实例,然后通过高 public SqlSessionFactory build(Configuration config) ;去创建SqlSessionFactory实例;

2、从XML中构建SqlSessionFactory :

实际上就是我们平常开发中常用的通过XML文件中构建SqlSessionFactory的实例;

不使用XML构建SqlSessionFactory,比较简单,我们这里主要看看从XML中构建SqlSessionFactory 的过程:
    //通过XMLConfigBuilder解析mybatis配置,然后创建SqlSessionFactory对象
    //参数reader:根据XML文档获取的Reader实例。
    //参数environment:决定加载哪种环境(开发环境/生产环境)
    //参数properties:那些properties(属性配置文件),那些属性可以用${propName}语法在配置文件中使用
    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        SqlSessionFactory var5;
        try {
            //委托XMLConfigBuilder来解析xml文件
            XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
            //构建SqlSessionFactory
            var5 = this.build(parser.parse());
        } catch (Exception var14) {
            throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
        } finally {
            ErrorContext.instance().reset();

            try {
                reader.close();
            } catch (IOException var13) {
                ;
            }

        }

        return var5;
    }

接着我们来看看:
new XMLConfigBuilder(reader, environment, properties):

public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
  }

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;
  }

从代码我们可以看出来XMLConfigBuilder构健过程初始化的组件有:
Reader:通过xml配置文件获取的实例Reader
Properties:properties的配置信息对应的实例Properties
Evironment:环境对象
XMLMapperEntityResolver:DTDs校验xml配置语法的对象
XPathParser:xml的解析器。

接着我们来看看:SqlSessionthis.build(parser.parse()) :
先看下中:parser.parse():

public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    //从根节点configuration
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

  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);
    }
  }

从上面的代码我们就能看出,在mybatis的配置文件中:configuration节点之下,可以配置的信息分别为:
Properties全局参数
TypeAliases别名
Plugin插件
ObjectFactory对象
objectWrapperFactory
Settings设置
Environment环境
DatabaseidProvider 数据库标识
TypeHandler类型处理器
Mapper映射器

最后通过build(Configuration config)构建SqlSessionFactory:

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
总结下:
SqlSessionFactory构建过程(SqlSessionFactoryBuilder):
第一步:通过XMLConfigBuilder解析XML文件,读取配置信息,并保存到Configuration类中。备注:Mybatis几乎所有的配置都是保存在Configuration
第二部:使用Confinguration对象去创建SqlSessionFactory。备注:SqlSessionFactory是一个接口。
构建Configuration构建过程:

第一步:读取配置文件,包括基础配置的XML文件和映射器的XML文件
第二步:初始化基础配置比如Mybatis的别名等,一些重要的类对象,(插件,映射器,ObjectFatory,typeHandler对象等)
第三步:提供单例,为后续创建SessionFactory服务并提供配置参数
第四步:执行一些重要的对象方法,初始化配置信息。

初始化:
Properties全局参数
Settings设置
TypeAliases别名
TypeHandler类型处理器
ObjectFactory对象
Plugin插件
Environment环境
DatabaseidProvider 数据库标识
Mapper映射器

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,460评论 0 4
  • MyBatis 理论篇 [TOC] 什么是MyBatis  MyBatis是支持普通SQL查询,存储过程和高级映射...
    有_味阅读 2,889评论 0 26
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 1 引言# 本文主要讲解JDBC怎么演变到Mybatis的渐变过程,重点讲解了为什么要将JDBC封装成Mybait...
    七寸知架构阅读 76,442评论 36 980
  • 1、URI和URL含义: 在理解URL之前先来看一下什么是URI 1.1 什么是URI? 简单点说:URI就是通用...
    尼古拉斯_特仑苏阅读 3,786评论 0 0