MyBatis源码分析之抽象工厂模式和建造者模式的应用

抽象工厂模式的应用

MyBatis源码的注释不多,不过SqlSession倒是给了两行注释:

/**
 * The primary Java interface for working with MyBatis.
 * Through this interface you can execute commands, get mappers and manage transactions.
 * @author Clinton Begin
 */
public interface SqlSession extends Closeable {}

第一行注释告诉我们SqlSession是使用MyBatis的主要接口,SqlSession有一个默认的实现类DefaultSqlSession,另外一个实现类SqlSessionManager(通过实现接口SqlSessionFactory,增加了工厂的能力)在后面的博文中会有详细的分析。

再看SqlSessionFactory只给了一行注释:

/**
 * Creates an {@link SqlSession} out of a connection or a DataSource
 * @author Clinton Begin
 */
 public interface SqlSessionFactory {}

注释告诉我们,接口SqlSessionFactory用于从数据源或数据库连接中创建SqlSession,SqlSessionFactory也有一个默认的实现类DefaultSqlSessionFactory,另外一个实现类SqlSessionManager,再次不做赘述。

下面看DefaultSqlSessionFacotry中实际产生SqlSession对象的两个方法(从数据源和数据库连接中获取):

// 从数据源中打开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);
      // 实际返回的是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();
    }
}

// 从数据库连接中打开Session
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
      boolean autoCommit;
      try {
        autoCommit = connection.getAutoCommit();
      } catch (SQLException e) {
        // Failover to true, as most poor drivers
        // or databases won't support transactions
        autoCommit = true;
      }      
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      final Transaction tx = transactionFactory.newTransaction(connection);
      final Executor executor = configuration.newExecutor(tx, execType);
      // 实际返回的是DefaultSqlSession
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}

从上面的代码得知,实际由DefaultSqlSessionFactory生产DefaultSqlSession对象。

通过上面的分析,可以看出SqlSession和SqlSessionFactory这两个接口,及DefaultSqlSession和DefaultSqlSessionFactory这两个默认实现类,就是典型的抽象工厂模式的实现。

建造者模式的应用

上面讲述了SqlSession的实现类的产生过程,那么SqlSessionFactory是怎么产生的呢?

SqlSessionFactory是由SqlSessionFactoryBuilder产生的,代码如下:

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

DefaultSqlSessionFactory的构造器需要传入MyBatis核心配置类Configuration的对象作为参数,而Configuration庞大且复杂,初始化比较麻烦,使用了专门的建造者XMLConfigBuilder进行构建。

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      // 创建建造者XMLConfigBuilder实例
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      // XMLConfigBuilder的parse()构建Configuration实例
      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.
      }
    }
 }

XMLConfigBuilder负责Configuration实例各个组件的创建和装配,整个装配的流程化过程如下:

private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      // Configuration#
      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);
    }
}

XMLConfigBuilder负责创建复杂对象Configuration,SqlSessionFactoryBuilder只不过是做了一层封装去构建SqlSessionFactory实例,这是建造者模式的简化构建过程。


  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值