MyBatis 的 Executor 结构分析

介绍

该笔记是在学习拉勾教育 Java 高薪训练营后,结合课程和老师的视频,自己跟踪源码后做的笔记。

Executor 结构

如下图,Executor 的默认实现类为 BaseExecutor,实现 Executor 接口的大部分功能。

在这里插入图片描述

  • BaseExecutor,Executor 接口的默认实现类,实现 Executor 接口的大部分功能;
  • ClosedExecutor,已关闭的 Executor;
  • CachingExecutor,支持二级缓存的 Executor 的实现类。先从缓存中查询结果,存在就返回。否则会给一级缓存执行器(BatchExecutor、ReuseExecutor、SimpleExecutor)去获取数据;
  • BatchExecutor,批量执行的 Executor 实现类,缓存多个 Statement 对象,等待统一执行;
  • ReuseExecutor,可重用的 Executor 实现类,指重复使用 Statement;
    1. 每次开始读或写操作,优先从缓存中获取对应的 Statement 对象。如果不存在,才进行创建,并保存到 Map 中;
    2. 执行完成后,不关闭该 Statement 对象。
  • SimpleExecutor,简单的 Executor 实现类,默认使用的执行器;
    1. 每次开始读或写操作,都创建对应的 Statement 对象;
    2. 执行完成后,关闭该 Statement 对象。
区别
  • CachingExecutor,二级缓存执行器,二级缓存没获取到,在走一级缓存流程;
  • BatchExecutor,先缓存多个 Statement 对象,在统一执行;
  • ReuseExecutor,重复使用 Statement,先从缓存中获取 Statement;
  • SimpleExecutor,执行一次就创建一个 Statement,执行完就关闭。

newExecutor

为创建执行器代码。

  • 根据 ExecutorType 类型来选择一级缓存执行器,BATCH 为 BatchExecutor,REUSE 为 ReuseExecutor,其余都为 SimpleExecutor;
  • 看出二级缓存 CachingExecutor 会存入一个一级缓存执行器,先进行二级缓存查找,找不到在调用一级缓存执行器查找。
    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        // 获得执行器类型
        executorType = executorType == null ? defaultExecutorType : executorType; // 使用默认
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType; // 使用 ExecutorType.SIMPLE
        // 创建对应实现的 Executor 对象
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new ReuseExecutor(this, transaction);
        } else {
            executor = new SimpleExecutor(this, transaction);
        }
        // 如果开启缓存,创建 CachingExecutor 对象,进行包装
        if (cacheEnabled) {
            executor = new CachingExecutor(executor);
        }
        // 应用插件
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
    }

设计模式

Executor 接口 -> 抽象类 BaseExecutor -> 具体子类 BatchExecutor,这种结构典型使用了模板方法的设计模式,在抽象方法中封装了整体逻辑流程,其中的某个方法则为抽象方法,由子类实现。
  如下代码,BaseExecutor#update 封装了更新的整体流程,而 doUpdate 为抽象方法,由具体子类实现。

    @Override
    public int update(MappedStatement ms, Object parameter) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
        // 已经关闭,则抛出 ExecutorException 异常
        if (closed) {
            throw new ExecutorException("Executor was closed.");
        }
        // 清空本地缓存
        clearLocalCache();
        // 执行写操作
        return doUpdate(ms, parameter);
    }
    
    protected abstract int doUpdate(MappedStatement ms, Object parameter)
            throws SQLException;
SimpleExecutor#doUpdate

继承抽象类 BaseExecutor 并实现其抽象方法 doUpdate。看出代码逻辑,会创建 StatementHandler 对象,然后执行 update 操作,最后关闭 StatementHandler。

    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;
        try {
            Configuration configuration = ms.getConfiguration();
            // 创建 StatementHandler 对象
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            // 初始化 StatementHandler 对象
            stmt = prepareStatement(handler, ms.getStatementLog());
            // 执行 StatementHandler ,进行写操作
            return handler.update(stmt);
        } finally {
            // 关闭 StatementHandler 对象
            closeStatement(stmt);
        }
    }

reference

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值