Executor介绍

1.Executor介绍:

Executor是mybatis的核心接口之一,其中定义了数据库操作的基本方法,它的子类结构图如下:这这张关系图中,涉及到了模板方法模式和装饰器模式。BaseExecutor是一个抽象父类,定义了一级缓存和事务相关的公共的固定不变的方法,同时定义了doUpdate,doQuery等抽象方法,这些抽象方法是在BaseExecutor的四个子类中实现的。这里用到了模板方法模式。对于CachingExecutor这个类,它为Executor提供了二级缓存的功能,它是一个装饰类,被装饰的目标类是BaseExecutor的四个子类,比如是SimpleExecutor,所以这里用到了装饰器模式。

2.源码分析:

2.1 Executor源码:

public interface Executor {

  ResultHandler NO_RESULT_HANDLER = null;
  // 执行update,insert,delete三种类型的SQL
  int update(MappedStatement ms, Object parameter) throws SQLException;
  // 执行select类型的SQL
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
  // 批量执行SQL
  List<BatchResult> flushStatements() throws SQLException;
  // 事务提交
  void commit(boolean required) throws SQLException;
  // 事务回滚
  void rollback(boolean required) throws SQLException;
  // 创建一级缓存中使用到的CacheKey对象
  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

  boolean isCached(MappedStatement ms, CacheKey key);
  // 清空一级缓存
  void clearLocalCache();

  void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
  // 获取事务对象
  Transaction getTransaction();

  void close(boolean forceRollback);

  boolean isClosed();

  void setExecutorWrapper(Executor executor);

}

2.2 BaseExecutor

BaseExecutor是一个实现了Executor的抽象类,它实现了Executor的大部分方法,比如:一级缓存管理和事务管理的基本功能,它的四个子类只需要实现doQuery,doUpdate等抽象方法来完成数据库的相关操作。

public abstract class BaseExecutor implements Executor {

  private static final Log log = LogFactory.getLog(BaseExecutor.class);

  protected Transaction transaction;  // transaction对象
  protected Executor wrapper; // 封装的executor对象 

  protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
  protected PerpetualCache localCache; // 一级缓存 用于缓存该Executor对象查询结果集映射得到的结果对象
  protected PerpetualCache localOutputParameterCache;
  protected Configuration configuration;

  protected int queryStack = 0;
  private boolean closed;
   // 获取transaction对象
  public Transaction getTransaction() {
    if (closed) throw new ExecutorException("Executor was closed.");
    return transaction;
  }

 public int update(MappedStatement ms, Object parameter) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
    if (closed) throw new ExecutorException("Executor was closed.");
    clearLocalCache();
    return doUpdate(ms, parameter);
  }
  // 批量执行多条缓存的SQL
  public List<BatchResult> flushStatements(boolean isRollBack) throws SQLException {
    if (closed) throw new ExecutorException("Executor was closed.");
    return doFlushStatements(isRollBack);
  }

  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
 }
    // 先查询一级缓存,如果未命中,则再查询数据库
  @SuppressWarnings("unchecked")
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) throw new ExecutorException("Executor was closed.");
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {        // 此处会调用在子类中实现的doQuery方法,默认的子类是SimpleExecutor
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      deferredLoads.clear(); // issue #601
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        clearLocalCache(); // issue #482
      }
    }
    return list;
  }

  // 事务提交
  public void commit(boolean required) throws SQLException {
    if (closed) throw new ExecutorException("Cannot commit, transaction is already closed");
    clearLocalCache();
    flushStatements();
    if (required) {
      transaction.commit();
    }
  }
    // 事务回滚
  public void rollback(boolean required) throws SQLException {
    if (!closed) {
      try {
        clearLocalCache();
        flushStatements(true);
      } finally {
        if (required) {
          transaction.rollback();
        }
      }
    }
  }
    // 需要在子类中实现的update操作
  protected abstract int doUpdate(MappedStatement ms, Object parameter)
      throws SQLException;

  protected abstract List<BatchResult> doFlushStatements(boolean isRollback)
      throws SQLException;
  // 需要在子类中实现的query操作
  protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
      throws SQLException;
  }

}

由上面的query方法可知,BaseExecutor提供了一级缓存的查询功能,如果一级缓存未命中,则再会调用在它的子类中实现的doQuery方法,默认的子类是SimpleExecutor。

2.3 SimpleExecutor

SimpleExecutor继承了BaseExecutor抽象类,它是最简单的Executor接口的实现。这里使用到了模板方法模式,一级缓存和事务管理等固定不变的操作封装到了BaseExecutor这个父类中,而update,query等与数据库交互的基本方法,都在子类中实现的。

public class SimpleExecutor extends BaseExecutor {

  public SimpleExecutor(Configuration configuration, Transaction transaction) {
    super(configuration, transaction);
  }
  // upate,insert,delete操作
  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.update(stmt);
    } finally {
      closeStatement(stmt);
    }
  }
  // query操作
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();      // 创建StatementHandler对象
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);      // 完成Statement的创建和初始化
      stmt = prepareStatement(handler, ms.getStatementLog());      // 调用StatementHandler.query方法,执行SQL语句,并通过ResultSetHandler完成结果集的映射
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

}

对于另外三个子类这里就不做分析了。接下来介绍CachingExecutor这个类

2.4 CachingExecutor

对于CachingExecutor,通过装饰器模式,为Executor增加了二级缓存的功能,接下来就对它的属性和主要方法做个分析:

2.4.1 属性:

  private Executor delegate; // 被装饰的类,也成为目标类
  private TransactionalCacheManager tcm = new TransactionalCacheManager(); // 用于管理Cahce和TransactionCache,也就是和二级缓存相关的

2.4.2 查询方法:

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    Cache cache = ms.getCache();    // 如果映射配置文件中配置了<cache/>,则此处cache!= null
    if (cache != null) {
      flushCacheIfRequired(ms);      // 查询节点的useCache配置以及是否是否使用了resultHandler
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, parameterObject, boundSql);
        @SuppressWarnings("unchecked")        // 查询二级缓存
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {          // 如果二级缓存没有查询出结果,会调用封装的Executor对象的query方法,其中会先查询一级缓存,再执行数据库查询操作
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
        }
        return list;
      }
    }    // 没有启动二级缓存,直接调用底层Executor执行数据库的查询操作
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

 2.4.3 事务提交:

  public void commit(boolean required) throws SQLException {
    delegate.commit(required); // 调用底层的Executor提交事务
    tcm.commit(); // 遍历所有的TransactionCahce对象执行commit方法
  }

关于Executor就暂时说这么多吧,其实这些内容在其他文章中都有提到,这里不过是做一个简单的分类总结。

原文地址:https://www.cnblogs.com/51life/p/9647428.html

时间: 2024-11-04 15:35:23

Executor介绍的相关文章

Java 并发专题 : Executor详细介绍 打造基于Executor的Web服务器

适配器模式,将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 应用场景:系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配.适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况. 代码实现: //Adapter.h #include "stdafx.h" #include <iostream> class Adaptee

java中Executor、ExecutorService、ThreadPoolExecutor介绍

java中Executor.ExecutorService.ThreadPoolExecutor介绍 ExecutorService 的理解与使用

Executor等系列概念介绍

这里对几个常见的的名词进行介绍 Executor 这是个接口,只声明了一个方法—— public interface Executor { void execute(Runnable command);---执行一个Runnable对象 } Executors 然后是Executors类,这个可以看作是个公共类,它提供了许多强大有用的获取线程池的static方法: 1.public static ExecutorService newFixedThreadPool(int nThreads) 创

java多线程之Executor框架线程池详细介绍与ThreadPoolExecutor

Executor框架简介 Executor框架的结构 Executor框架主要由3大部分组成: 任务: 包括被执行的任务需要实现的接口:Runable 接口.Callable接口: 任务的执行: 包括任务执行机制的核心接口Executor,以及继承自Executor的ExecutorService接口.Executor框架有两个关键类实现了ExecutorService接口:ThreadPoolExecutor 和 ScheduledThreadPoolExecutor.ForkJoinPool

Java 线程池(一):开篇及Executor整体框架介绍

一.开篇 线程池.数据库连接池,在平时的学习中总能接触到这两个词,但它们到底是什么?和线程,数据库连接有什么关系?为什么需要“池”?“池”的概念及作用是什么?要弄清楚这些问题,就要深入到“池”的实现中去. 之前找实习工作时,时常有面试官问这类问题,自己平时知道如何使用Java的Executor线程池框架,但是具体的细节还真没感受,所以打算开始试着研究一下Executor线程池框架. 废话到此打住,正式开始! 二.Executor整体框架 让我们先站在一个较高的角度俯视一下Java线程池的整体结构

java中Executor、ExecutorService、ThreadPoolExecutor介绍(转)

1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /**     * Executes the given command at some time in the future.  The command     * may execute in a new thread, in a pooled thread, or in the calling     * thread, at the

Java多线程框架Executor详解

原文链接  http://www.imooc.com/article/14377 为什么引入Executor线程池框架new Thread()的缺点 每次new Thread()耗费性能调用new Thread()创建的线程缺乏管理,被称为野线程,而且可以无限制创建,之间相互竞争,会导致过多占用系统资源导致系统瘫痪.不利于扩展,比如如定时执行.定期执行.线程中断 采用线程池的优点 重用存在的线程,减少对象创建.消亡的开销,性能佳可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争

Spark 学习: spark 原理简述与 shuffle 过程介绍

Spark学习: 简述总结 Spark 是使用 scala 实现的基于内存计算的大数据开源集群计算环境.提供了 java,scala, python,R 等语言的调用接口. Spark学习 简述总结 引言 1 Hadoop 和 Spark 的关系 Spark 系统架构 1 spark 运行原理 RDD 初识 shuffle 和 stage 性能优化 1 缓存机制和 cache 的意义 2 shuffle 的优化 3 资源参数调优 4 小结 本地搭建 Spark 开发环境 1 Spark-Scal

JAVA多线程之间共享数据BlockingQueue介绍

在JAVA的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利.本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景. 一.认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示:  从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从