zoukankan      html  css  js  c++  java
  • Mybatis源码(一) 之SqlSession的创建

    Mybatis源码(一) 之SqlSession的创建

    近日学习了mybatis的源码,记录一下sqlSessionFactory的创建过程,SqlSessionFactory 是通过SqlSessionFactoryBuilder创建的,如下所示

    // 获取Mybatis配置文件输入流
    Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
    // 通过SqlSessionFactoryBuilder创建SqlSessionFactory实例
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
    // 调用SqlSessionFactory的openSession()方法,创建SqlSession实例
    SqlSession session = sqlSessionFactory.openSession();
    

     

    SqlSessionFactoryBuilder的相关源码如下:

    public class SqlSessionFactoryBuilder {
    
      public SqlSessionFactory build(Reader reader) {
        return build(reader, null, null);
      }
    
      public SqlSessionFactory build(Reader reader, String environment) {
        return build(reader, environment, null);
      }
    
      public SqlSessionFactory build(Reader reader, Properties properties) {
        return build(reader, null, properties);
      }
    
      public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
          return build(parser.parse());
        } catch (Exception e) {
          throw ExceptionFactory.wrapException("Error building SqlSession.", e);
        } finally {
          ErrorContext.instance().reset();
          try {
            reader.close();
          } catch (IOException e) {
            // Intentionally ignore. Prefer previous error.
          }
        }
      }
    
      public SqlSessionFactory build(InputStream inputStream) {
        return build(inputStream, null, null);
      }
    
      public SqlSessionFactory build(InputStream inputStream, String environment) {
        return build(inputStream, environment, null);
      }
    
      public SqlSessionFactory build(InputStream inputStream, Properties properties) {
        return build(inputStream, null, properties);
      }
      //通过XMLConfigBuilder解析mybatis配置,然后创建SqlSessionFactory对象
      public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
        try {
          XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
          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.
          }
        }
      }
        
      public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
      }
    
    }
    

     XMLConfigBuilder 中主要就做了一个创建XPathParser解析器的工作,并把解析器放入到XMLConfigBuilder中

    XMLConfigBuilder部分源码如下:

    XmlConfigBuilder的parseConfiguration方法解析xml是根据Xpath方式解析的。解析相应的标签之后,又把属性赋值给Configuration对象。最后返回

    public class XMLConfigBuilder extends BaseBuilder {
    
      private boolean parsed;
      private final XPathParser parser;
      private String environment;
      private final ReflectorFactory localReflectorFactory = new DefaultReflectorFactory();
    
      public XMLConfigBuilder(Reader reader) {
        this(reader, null, null);
      }
    
      public XMLConfigBuilder(Reader reader, String environment) {
        this(reader, environment, null);
      }
    
      public XMLConfigBuilder(Reader reader, String environment, Properties props) {
        this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
      }
    
      public XMLConfigBuilder(InputStream inputStream) {
        this(inputStream, null, null);
      }
    
      public XMLConfigBuilder(InputStream inputStream, String environment) {
        this(inputStream, environment, null);
      }
    
      public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
        this(new XPathParser(inputStream, 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;
      }
    
      public Configuration parse() {
        // 防止parse()方法被同一个实例多次调用
        if (parsed) {
          throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        }
        parsed = true;
        // 调用XPathParser.evalNode()方法,创建表示configuration节点的XNode对象。
        // 调用parseConfiguration()方法对XNode进行处理
        parseConfiguration(parser.evalNode("/configuration"));
        return configuration;
      }
    
      // 解析mybatis-config文件中的标签
      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);
        }
      }
    

    由以上源码可知,build方法中XMLConfigBuilder 解析mybatis-config.xml文件得到Configuration对象。然后调用如下方法,创建的对象

    SqlSessionFactory是一个接口,所以创建他的默认实现。DefaultSqlSessionFactory

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

      

    SqlSessionFactory是一个接口,可以通过接口中的 SqlSession openSession(); 方法获取SqlSession的实例。

    SqlSessionFactory接口代码

    public interface SqlSessionFactory {
    
      SqlSession openSession();
    
      SqlSession openSession(boolean autoCommit);
      SqlSession openSession(Connection connection);
      SqlSession openSession(TransactionIsolationLevel level);
    
      SqlSession openSession(ExecutorType execType);
      SqlSession openSession(ExecutorType execType, boolean autoCommit);
      SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
      SqlSession openSession(ExecutorType execType, Connection connection);
    
      Configuration getConfiguration();
    
    }
    

    SqlSession也是一个接口,DefaultSqlSession是其实现类

    选择实现类 DefaultSqlSessionFactory 源码片段

    public class DefaultSqlSessionFactory implements SqlSessionFactory {
    
      private final Configuration configuration;
    
      public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
      }
    
      @Override
      public SqlSession openSession() {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
      }
    
       private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
          // 获取Mybatis主配置文件配置的环境信息
          final Environment environment = configuration.getEnvironment();
          // 创建事务管理器工厂
          final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
          // 创建事务管理器
          tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
          // 根据Mybatis主配置文件中指定的Executor类型创建对应的Executor实例
          final Executor executor = configuration.newExecutor(tx, execType);
          // 创建DefaultSqlSession实例
          return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
          closeTransaction(tx); // may have fetched a connection so lets call close()
          throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
          ErrorContext.instance().reset();
        }
      }
    }
    

    由此,SqlSession的实例就创建完成了

     给自己画个粗糙的流程图

      

  • 相关阅读:
    Hibernate 3入門
    如何调整液晶显示器保护你的视力
    WEB前端开发经验总结实战篇
    【JS】引用类型之Array
    Oracle的DBA管理常用sql
    使用cos组建上传文件
    前台js将json转换成json对象的方法
    关于父页面访问iframe中元素和js的那点事
    数据库中IN和EXISTS的区别
    关于google浏览器有时莫名自动提交表单的问题
  • 原文地址:https://www.cnblogs.com/yingxiaocao/p/13539694.html
Copyright © 2011-2022 走看看