zoukankan      html  css  js  c++  java
  • MyBatis源码分析-MyBatis初始化流程

      MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA新建MyBatis源码工程

      MyBatis初始化的过程也就是创建Configuration对象的过程,下面以XML方式为例说明MyBatis是如何完成初始化的(完整测试代码点击MyBatis源码分析-SQL语句执行的完整流程)。

    String resouce = "conf.xml";
    InputStream is = Resources.getResourceAsStream(resouce);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    SqlSession session = sqlSessionFactory.openSession();
    user = session.selectOne("com.luoxn28.dao.UserDao.getById", 1);

      以上代码经过了MyBatis初始化、创建SQLSession、执行SQL语句3个过程。根据conf.xml配置文件创建SqlSessionFactory对象,然后创建SqlSession对象,执行SQL语句。其中,MyBatis的初始化就发生在SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is)

           MyBatis初始化基本过程总结如下:SqlSessionFactoryBuilder根据传入的数据流生成Configuration对象,然后根据Configuration对象创建默认的SqlSessionFactory实例。其中序列图如下:

    上图的初始化过程经过以下的几步:

    • 1. 调用SqlSessionFactoryBuilder对象的build(inputStream)方法;
    • 2. SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
    • 3. SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;
    • 4. XMLConfigBuilder对象返回Configuration对象;
    • 5. SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
    • 6. SqlSessionFactoryBuilder返回 DefaultSessionFactory对象给Client,供Client使用。

    SqlSessionFactoryBuilder相关代码:

    public SqlSessionFactory build(InputStream inputStream) {
      return build(inputStream, null, null);
    }
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      try {
        // 1. 创建XMLConfigBuilder对象解析XML配置
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        // 2. 将XML配置解析成Configuration对象,通过Configuration对象创建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.
        }
      }
    }
    /**
     * 内部通过Configuration对象创建SqlSessionFactory,也可以通过Java API方式创建Configuration对象,
     * 然后调用该方法创建SqlSessionFactory
     */
    public SqlSessionFactory build(Configuration config) {
      return new DefaultSqlSessionFactory(config);
    }

    创建Configuration对象过程

      接着上述的 MyBatis初始化基本过程讨论,当SqlSessionFactoryBuilder执行build()方法,调用了XMLConfigBuilder的parse()方法,然后返回了Configuration对象。那么parse()方法是如何处理XML文件,生成Configuration对象的呢?

      1. XMLConfigBuilder会将XML配置文件的信息转换为Document对象,而XML配置定义文件DTD转换成XMLMapperEntityResolver对象,然后将二者封装到XpathParser对象中,XpathParser的作用是提供根据Xpath表达式获取基本的DOM节点Node信息的操作。如下图所示:

      2. 之后XMLConfigBuilder调用parse()方法:会从XPathParser中取出 <configuration>节点对应的Node对象,然后解析此Node节点的子Node:properties, settings, typeAliases,typeHandlers, objectFactory, objectWrapperFactory, plugins, environments,databaseIdProvider, mappers等。

    public Configuration parse() {
      if (parsed) {
        throw new BuilderException("Each XMLConfigBuilder can only be used once.");
      }
      parsed = true;
      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);
      }
    }

      解析出XML中对应的值后就设置到Configuration对象中,具体解析过程可以阅读对应源代码。Configuration对象创建好之后就会返回,并由此创建DefaultSqlSessionFactory对象。

      mapper.xml文件是在 mapperElement(root.evalNode("mappers")); 中解析的。

    参考:

    1、《深入理解mybatis原理》 Mybatis初始化机制详解

    2、MyBatis源码分析-IDEA新建MyBatis源码工程

    3、MyBatis源码分析-SQL语句执行的完整流程

  • 相关阅读:
    Simpo
    Numpy技巧
    流程图
    注册免费试用12个月的亚马逊AWS云计算服务
    java-Collection
    CoreGraphic
    吴裕雄--天生自然python学习笔记:python 用pygame模块开发俄罗斯方块游戏
    吴裕雄--天生自然python学习笔记:python 用pygame模块检测键盘事件和鼠标事件
    吴裕雄--天生自然python学习笔记:python 用pygame模块角色类(Sprite)移动与碰撞
    吴裕雄--天生自然python学习笔记:python 用pygame模块动画一让图片动起来
  • 原文地址:https://www.cnblogs.com/luoxn28/p/6002204.html
Copyright © 2011-2022 走看看