MyBatis之配置文件解析_环境environments的作用及处理

环境对象

Environment对象 环境对象是一个类,提供联接数据库的环境,mybatis支持多环境开发,可配置多个环境,根据环境不同,使用其中的一个。Confguration对象持有一个Environment对象,构建Configuration时,可以传入环境id,即使用指定的环境配置,或者使用默认的配置。Environment持有一个TransactionFactory及DataSource对象,环境对象通过解析XML配置文件的元素environments来构建。

public final class Environment {
  // 环境id,不同的id表示不同的环境  
  private final String id;
  // 创建事务的工厂  
  private final TransactionFactory transactionFactory;
  // 数据源对象, java.sql.DataSource  
  private final DataSource dataSource;
  // 可以通过构造方法创建Envionment对象  
  // 也可通过静态内部类Builder来构建
  public static class Builder {}     
}

配置文件中环境的配置

配置文件中环境的配置主要指与数据库联接的配置,mybatis支持多环境的配置。enviomnents下可配置多个enviroment,若指定了所使用的id,则就使用这个id的environment,否则使用的id为environments属性default指定的environment。

<!-- mybatis环境相关配置  -->
<environments default="development">
    <environment id="development">
        <!-- 事务工厂的类型, JDBC是mybatis提供的 -->
        <transactionManager type="JDBC"/>
        <!-- 数据源类型, POOLED是mybatis提供的,配置的类型是DataSourceFactory -->
        <dataSource type="POOLED">
            <!-- 这种形式的配置,解析时转换为Properties对象, 创建DataSource对象,可以用这里的name-value,设置属性值 -->
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${uname}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
    <!-- 可以配置多个环境 -->
</environments>

environments标签的解析

XMLConfigBuilder的方法environmentsElement用来解析environments标签,构造好Environment对象,并保存在Configuration对象。解析时,若SqlSessionFactoryBuilder在创建XMLConfigBuilder对象时传入一个字符串environment,则这个字符串对应着标签environmentid属性,若没有传入则使用environments标签的default属性值作为environment字符串的值,用这个字符串匹配标签environmentid属性,匹配到则使用这个environment标签的配置创建Environment对象。

// 解析environments标签
private void environmentsElement(XNode context) throws Exception {
  if (context != null) {
    // environment是构造XMLConfigBuilder对象时外部传入的environment的id,若不空,则就用这个id指定的environment  
    if (environment == null) {
      // 若为null,则使用environment属性default的值作为environment的id   
      environment = context.getStringAttribute("default");
    }
    for (XNode child : context.getChildren()) {
      String id = child.getStringAttribute("id");
      if (isSpecifiedEnvironment(id)) {
        // 获得TransactionFactory对象  
        TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
        // 获得DataSourceFactory对象
        DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
        DataSource dataSource = dsFactory.getDataSource();
        // 构造Environment对象  
        Environment.Builder environmentBuilder = new Environment.Builder(id)
            .transactionFactory(txFactory)
            .dataSource(dataSource);
        // 将Environment对象保存到configuration对象中  
        configuration.setEnvironment(environmentBuilder.build());
      }
    }
  }
}

TransactionFactory及相关类

TransactionFactory是一个接口,用来构造事务Transaction对象,Transaction是一个用来进行事务处理(提交与回滚)的接口。

public interface TransactionFactory {
  default void setProperties(Properties props) {
    // NOP
  }
  Transaction newTransaction(Connection conn);
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);

}

mybatis提供的TransactionFactory的实现类是JdbcTransactionFactory及ManagedTransactionFactory,它们创建的Transaction的对象分别是JdbcTransaction及ManagedTransaction,在Configuration构造方法中注册了JdbcTransactionFactory及ManagedTransactionFactory这两个类型,别名分别为JDBC及MANAGED

public Configuration() {
  // mybatis默认注册的TransactionFactory  
  typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
  typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
}  

JdbcTransaction代码示例

​ JdbcTransactionFactory创建的Transaction对象是JdbcTransaction,JdbcTransaction使用Connection对象提交与回滚事务,下面是JdbcTransaction中提交事务的代码

public class JdbcTransaction implements Transaction {
  protected Connection connection;
  protected DataSource dataSource;
  protected TransactionIsolationLevel level;
  protected boolean autoCommit;
  @Override
  public void commit() throws SQLException {
      // 使用Connection对象提交事务
      if (connection != null && !connection.getAutoCommit()) {
          if (log.isDebugEnabled()) {
            log.debug("Committing JDBC Connection [" + connection + "]");
          }
      	  connection.commit();
    }
  }
}    

TransactionFactory对应的XML配置,在environment的子标签transactionManager中,如下所示

 <environment id="development">
        <!-- 事务工厂的类型, JDBC是mybatis提供的,对应的实现类是JdbcTransactionFactory -->
		<transactionManager type="JDBC"/>
</environment>		

transactionManager标签的解析

这个解析很简单,即从type属性中获得TransactionFactory的类型,创建这个对象返回,由Envionment对象使用。

private TransactionFactory transactionManagerElement(XNode context) throws Exception {
  // 获得属性type的值,这是一个实现了TransactionFactory的类  
  if (context != null) {
    String type = context.getStringAttribute("type");
    Properties props = context.getChildrenAsProperties();
    // 获得这个类的对象,并返回,构建环境对象时,使用到这个对象  
    TransactionFactory factory = (TransactionFactory) resolveClass(type).getDeclaredConstructor().newInstance();
    factory.setProperties(props);
    return factory;
  }
  throw new BuilderException("Environment declaration requires a TransactionFactory.");
}

mybatis数据源配置及解析及数据库联接池的实现在下面的文章中介绍

posted @ 2022-04-27 16:48  beckwu  阅读(617)  评论(0)    收藏  举报