MyBatis源码学习笔记(三)

之前学习到

DefaultSqlSessionFactory中的

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到业务层使用。

可见Environment作为获取SqlSession的基础,在现在观察到的代码中,Configuration始终贯穿代码之中。

随之查看Environment的源码,

属性只有

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

Environment依然使用Builder模式。

由此属性看来,Environment关注的是事务类型,还有就是数据源,id使用与区分,参考文档中介绍了可以通过多个Environment实现多数据库的操作。

跟踪Environment的build方式,是由

XMLConfigBuilder中的

  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的配置。

之后应该要分析一下在这过程中代码中写得优雅的部分。

posted on 2013-10-16 23:40  错误王  阅读(321)  评论(0)    收藏  举报

导航