mybatis的执行器(Executor)创建过程

发布时间 2023-11-22 23:37:55作者: 神行诸葛

Executor是mybatis里面的核心对象之一,他提供了crud功能,可以认为这是一个门面。Executor有很多实现类。但是默认情况下,在你不配置Executor的类型的时候,会创建一个SimpleExecutor。

下面看一下他的类结构

那我们就来看看这个执行器是怎么创建的。

核心的地方就是在我们获取SqlSession对象的时候,创建了执行器。

DefaultSqlSessionFactory:

@Override
  public SqlSession openSession() {
    /**
     * 设置了一个默认的Executor 默认为simple
     * configuration.getDefaultExecutorType() 执行器的类型,默认为simple
     * 并且设置为手动提交事务
     */
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

这个configuration对象,就是解析我们mybatis的配置文件生成的对象。其实我们可以在mybatis的配置文件设置执行器的类型。这里暂时忽略吧。今天只讲simple这个执行器的生成。

继续看下面这个方法

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);
      //获取执行器的时候,进行了mybatis插件的添加
      final Executor executor = configuration.newExecutor(tx, execType);
      /**
       * 创建了一个默认的DefaultSqlSession
       * 并且DefaultSqlSession持有Configuration对象 还有执行器(cache) 设置了自动提交
       * 这个executor有可能是代理对象 executor中包含事务对象
       * 所以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();
    }
  }

 先看这行代码

final Executor executor = configuration.newExecutor(tx, execType);

这行代码就是配置文件解析生成的对象来创建一个执行器,参数就是mybatis生成的事务管理器和执行器类型(simple)。

进去这个方法看看

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    //这两行就是继续判断执行器类型,默认是simple
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      //如果是simple,走这里
      executor = new SimpleExecutor(this, transaction);
    }
    //默认为true,这个参数也可以在mybatis的配置文件中进行配置
    if (cacheEnabled) {
      //又套娃了,装饰器模式
      executor = new CachingExecutor(executor);
    }
    //调用插件,如果有配置的插件,那么返回代理对象,层层代理。套千层饼
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

这段代码难度不是很大,我们看这一行

if (cacheEnabled) {
      //又套娃了,装饰器模式
      executor = new CachingExecutor(executor);
    }

这里又进行了一次包装,这个CachingExecutor也是一个执行器,跟simple是兄弟关系。那么为什么要套一层呢?主要还是跟mybatis的缓存有关系。这里使用了装饰器模式。目的就是对功能的增强。

那这个又在干什么呢?

executor = (Executor) interceptorChain.pluginAll(executor);

这个是mybatis的插件机制。稍微复杂。其实PageHelper这个分页对象,就是利用了mybatis的插件机制。如果你配置了插件,那么有可能,你的执行器会是一个代理对象。只是有可能,不一定。这个要看你的插件代码怎么写。

这里不废话了。有机会给大家介绍mybatis插件。

好,关于执行器的创建就粗略分享这么多。