Mybatis构建SqlSessionFactory(2)201

2018-08-19  本文已影响0人  Seetheworl_6675

 今天我们来根据上一篇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映射器

上一篇下一篇

猜你喜欢

热点阅读