Mybatis3源码分析(10)-Executor接口实现方式

撸了今年阿里、腾讯和美团的面试,我有一个重要发现…….

作者:ashan_li

出处:https://blog.csdn.net/ashan_li/article/category/6047775/1?


之前介绍过,Executor接口定义了对象操作库操作的基本方法:select/update/insert/delete/commit/rollbak/close。Mybatis对Executor接口的实现主要采用了模板模式和装饰模式两种设计模式。

Executor类关系

2019080910010_1.png

其中CloseExecutor为一个类的内部了,而且是private的,先不讨论!

2019080910010_2.png

  1. BaseExecutor为模板模式中的模板类。这个类在Executor接口实现中非常重要,其实现了Executor的大部分方法。他的子类只要实现三个方法即可,其中两个是doUpdate和doSelect方法,子类在实现这两个方法时直接操作数据库即可,其余的工作交由BaseExecutor完成。
  2. CachingExecutor是一个Executor的装饰器,给一个Executor增加了缓存的功能。

模板模式和装饰模式前面分析加载Configuration中也用到,说明这个设计模式的重要性,这两种设计模式也在Spring中很多地方采用。作为java程序员应该详细解读并应用这两种设计模式!

Executor接口主要方法

    public interface Executor {
       //执行update/insert/delete
      int update(MappedStatement ms, Object parameter) throws SQLException;
      //执行查询
      <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;
      //以后有机会在分析
      List<BatchResult> flushStatements() throws SQLException;
      //事务提交
      void commit(boolean required) throws SQLException;
      //事务回滚
      void rollback(boolean required) throws SQLException;
      //生成缓存的key
      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);

    }

BaseExecutor

再来看看BaseExcutor模板是怎么实现Executor的

BaseExecutor有两个主要的属性:事务及本地缓存

    protected BaseExecutor(Configuration configuration, Transaction transaction) {
        //transaction,实现commit/rollback/close
        this.transaction = transaction;
        this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
        //本地缓存,也就是一级缓存
        this.localCache = new PerpetualCache("LocalCache");
        this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
        this.closed = false;
        this.configuration = configuration;
        this.wrapper = this;
      }

再来看看BaseExecutor是怎么实现查询和更新的

    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();
        //调用了doUpdate方法完成更新,这个方法是抽象的,由子类实现
        return doUpdate(ms, parameter);
      }
     protected abstract int doUpdate(MappedStatement ms, Object parameter)
          throws SQLException;

       //查询
      private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        List<E> list;
        localCache.putObject(key, EXECUTION_PLACEHOLDER);
        try {
         //调用doQuery方法,这个方法也是抽象的
          list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
        } finally {
          localCache.removeObject(key);
        }
        localCache.putObject(key, list);
        if (ms.getStatementType() == StatementType.CALLABLE) {
          localOutputParameterCache.putObject(key, parameter);
        }
        return list;
      }
    protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
          throws SQLException;

CachingExecutor实现缓存

     public CachingExecutor(Executor delegate) {
        //操作数据库的动作都是由这个Executor来完成的。
        this.delegate = delegate;
        delegate.setExecutorWrapper(this);
      }

对于Mybatis的缓存以后再详细分析。

赞(0) 打赏

如未加特殊说明,此网站文章均为原创,转载必须注明出处。Java 技术驿站 » Mybatis3源码分析(10)-Executor接口实现方式
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

关注【Java 技术驿站】公众号,每天早上 8:10 为你推送一篇技术文章

扫描二维码关注我!


关注【Java 技术驿站】公众号 回复 “VIP”,获取 VIP 地址永久关闭弹出窗口

免费获取资源

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏