MyBatis源碼學習筆記(三)

以前學習到數據庫

DefaultSqlSessionFactory中的session

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType, autoCommit);
      return new DefaultSqlSession(configuration, executor);
    } 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();
    }
  }

 

在此方法中,TransactionFactory依賴於Environment類,Transaction由Transaction Factory生成,Executor依賴於Transaction,最後DefaultSqlSession到業務層使用。app

可見Environment做爲獲取SqlSession的基礎,在如今觀察到的代碼中,Configuration始終貫穿代碼之中。ide

隨之查看Environment的源碼,源碼分析

屬性只有學習

  private final String id;
  private final TransactionFactory transactionFactory;
  private final DataSource dataSource;

Environment依然使用Builder模式。fetch

由此屬性看來,Environment關注的是事務類型,還有就是數據源,id使用與區分,參考文檔中介紹了能夠經過多個Environment實現多數據庫的操做。ui

跟蹤Environment的build方式,是由spa

XMLConfigBuilder中的xml

  private void parseConfiguration(XNode root) {
    try {
      propertiesElement(root.evalNode("properties")); //issue #117 read properties first
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      settingsElement(root.evalNode("settings"));
      environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
      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);
    }
  }

方法中的environmentsElement(root.evalNode("environments")); 生成Environment的。

  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          DataSource dataSource = dsFactory.getDataSource();
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }

來到此處終於找到參考文檔中的基本配置要素了!environments元素,transactionManager元素,dataSource元素。

在SqlSessionFactoryBuilder中,

 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());

經過輸入流,生成XMLConfigBuilder,XMLConfigBuilder的parse方法調用了

parseConfiguration方法設置Congfiguration並返回,並經過SqlSessionFactoyBuilder生成

DefaultSqlSessionFactory(此時SqlSessionFacoty已生成SqlSession)。

至此就完成了SqlSessionFactory生成SqlSession的源碼分析了。

算是解答了我以前想到的幾個問題了,SqlSessionFactoryBuilder,SqlSessionFacotyBuilder,基本xml的配置。

以後應該要分析一下在這過程當中代碼中寫得優雅的部分。

相關文章
相關標籤/搜索