《深入理解Mybatis原理》 01-Mybatis初始化机制

本文深入剖析MyBatis初始化过程,包括配置解析、Configuration对象创建及XML配置项映射。揭示了MyBatis如何从XML配置文件中读取设置,初始化默认配置项,并将自定义配置映射到Configuration对象。

对于大多数开发框架在使用之前都会经历 配置 ---->  初始化 过程,Mybatis也不例外。本章将通过以下几点深入源码详细讲解Mybatis初始化过程。

1.Mybatis初始化做了什么


2.Mybatis解析XML配置文件创建Configuration对象过程


1. Mybatis初始化做了什么?

    

/**
 * <p> In-Depth Study Mybatis with one</p>
 * @author jackcheng1117@163.com
 */
public class DemoApplication {

	public static void main(String[] args) throws IOException {
	//获取配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        //初始化Mybatis
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
    }
}

  Mybatis基本初始化流程图:

 

Mybatis初始化源码流程:

1. SqlSessionFactoryBuilder获取Mybatis配置文件流传递给XMLConfigBuilder对象


 //Mybatis初始化入口
 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //将配置流传递给XMLConfigBuilder解析XML文件,初始化Mybatis默认配置项
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      //parser.parse() : 初始化XML配置文件中配置
      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.
      }
    }
  }




2.创建XPathParser对象将XML配置文件解析为Docment配置项


 public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
    commonConstructor(validation, variables, entityResolver);
    //解析XML文件并生成Document
    this.document = createDocument(new InputSource(inputStream));
  }


3.初始化Mybatis配置项,生成Configuration对象

 //初始化Mybatis默认配置
 private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    //初始化Mybatis默认配置项
    super(new Configuration());
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
    this.parsed = false;
    this.environment = environment;
    this.parser = parser;
  }

  //XMLConfigBuilder parse方法 : 初始化XML配置文件中配置项  
  public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    //初始化XML中配置的配置
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }


4. Mybatis初始化完毕,返回SqlSessionFactory

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

  

综上所述,Mybatis初始化大致如下:


1. 调用 SqlSessionFactory的 build(InputStream inputStream) 方法

2. 创建 XPathParser对象将XML解析为 Document

3. 创建 XMLConfigBuilder对象,通过super(new Configuration) 初始化 Mybatis 默认配置

4. 调用 XMLConfigBuilder 对象的 parse() 方法初始化XML中配置项,并返回Configuration对象

5. 使用配置好的Configuration对象创建 SqlSessionFactory实现类DefaultSqlSessionFactory

 

   总结:

    初始化Mybatis的过程其实就是构建 Configuration 这个对象,Configuration对象包含了Mybatis运行所需要的所有配置项。

    MyBatis采用了一个非常直白和简单的方式---使用 org.apache.ibatis.session.Configuration 对象作为一个所有配置信息的容   器,Configuration对象的组织结构和XML配置文件的组织结构几乎完全一样(当然,Configuration对象的功能并不限于此,它还负责创建一些MyBatis内部使用的对象,如Executor等,这将在后续的文章中讨论)。如下图所示:


 

Mybatis初始化有两种方式:

基于XML配置文件:
    基于XML配置文件的方式是将MyBatis的所有配置信息放在XML文件中,MyBatis通过加载并XML配置文件,将配置文信息组装成内部的Configuration对象

基于Java API:
    这种方式不使用XML配置文件,需要MyBatis使用者在Java代码中,手动创建Configuration对象,然后将配置参数set 进入Configuration对象中


 

2. Mybatis解析XML配置文件创建Configuration对象过程

   章节一已将列出了Mybatis初始化的完整流程,Mybatis初始化时期本质上是初始化配置(即初始化Configuration对象),本章将详细讲解Mybatis是如何解析XML配置并初始化到Configuration的。

 

Step1: 初始化默认配置项

     当执行入口方法 SqlSessionFactoryBuilder.build(InputStream inputStream, String environment, Properties properties)时,

     首先会实例化出 XMLConfigBuilder,实例化过程中的 super(new Configuration()); 会进行初始化Mybatis默认配置项(即初始化Congiguration对象)

    new Configuration()主要执行的工作是:

        1. 初始化配置容器

        2. 注册配置实现类

 public Configuration() {
    typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
    typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);

    typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
    typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
    typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);

    typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
    typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
    typeAliasRegistry.registerAlias("LRU", LruCache.class);
    typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
    typeAliasRegistry.registerAlias("WEAK", WeakCache.class);

    typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);

    typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
    typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);

    typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
    typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
    typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
    typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
    typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
    typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
    typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);

    typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
    typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);

    languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
    languageRegistry.register(RawLanguageDriver.class);
  }

 

    Step2:初始化XML自定义配置项

 

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

  //解析XML自定义配置节点,并将配置映射到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原理》 Mybatis初始化机制详解 的全部内容,

上述内容如有不妥之处,还请读者指出,共同探讨,共同进步!

@author : jackcheng1117@163.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值