mybatis plugins_[Mybatis]-[基础支持层]-插件-多个插件执行顺序

755fa44f3062557e4e94d7fcc12d749b.png
该系列文章针对 Mybatis 3.5.1 版本

在 mybatis 中允许针对 SQL 在执行前后进行扩展操作,而这些扩展操作也叫做插件。

在 Mybaits 中允许用插件来拦截的方法包括:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

通过插件可以实现 SQL 打印,分页插件等功能。

这时候就会延伸出一个问题:如果存在多个插件,这些插件的执行顺序是怎样的?

一、插件的执行顺序

插件执行顺序一共有两种

1、不同拦截对象的执行顺序

Mybatis 提供了对如下四种对象的拦截,分别是:ExecutorParameterHandlerResultSetHandlerStatementHandler。针对这四种对象的拦截的执行顺序是固定的,因为 Mybatis 代码的执行流程是固定的。

SimpleExecutor#query 来说,这四种对象的执行代码如下:

如下述代码:

fbeb89a2ad3ff8c72f0fd8bbadfbe795.png

通过源码知道,执行顺序为:Executor` -> `StatementHandler` -> `ParameterHandler` -> `StatementHandler` -> `ResultSetHandler

虽然中间 StatementHandler 执行了多次,但是总的来说,执行顺序优先级从高到低为:Executor` -> `StatementHandler` -> `ParameterHandler` -> `ResultSetHandler

2、同种拦截对象的执行顺序

针对同种对象如果存在多种拦截器对象,其拦截顺序如何?

首先在前面的文章中,知道了插件功能的实现是通过代理的方式对原有的如:ExecutorParameterHandler 等进行了代理增强,而经过代理后的原有的 ExecutorParameterHandler 等对象会以如下方式存在:

bd9c2f3c05c723cf61c30a12ce3efccc.png

如图,存在多个拦截器都是先进后出,针对代理模式来说来说,可以对被代理的原始对象的处理前后进行代码增强操作。

而那个拦截器优先执行,取决于在生成代理对象时的顺序,也就是包裹在最外层的插件(拦截器)优先执行。

来回顾一下代理对象生成时的逻辑然后结合mybatis-config.xml 配置文件的关于 <plugins> 的配置信息,即可知道相关的执行顺序。

来看代理生成代码InterceptorChain#pluginAll,如下:

be8d4995330a91f071865ae04d38d8b9.png

如上述代码所示,通过遍历 interceptors List 列表对 target 对象进行包装(target 可以是 Executor or ParameterHandler等)。

也就是在 List 列表的最开始的 interceptor 插件最先被包裹在 target 对象外层,也就是如下图所示:

c608192db1f978a0374770a125b87834.png

如图,同个目标对象的多个拦截器的执行顺序,取决于mybatis 加载配置后,拦截器在 List<Interceptor> interceptors 中的顺序。

再来回顾一下 <plugins> 解析的关键代码,如下:

33d004db5f04a20d239648a347bc8ac3.png

如上图所示,在配置文件中越靠前的插件配置,在 interceptors List 列表中的位置自然越靠前,其执行顺序自然越靠后。

总结:同个对象的多个拦截器执行顺序根据配置文件 mybatis-config.xml 插件配置顺序有关,配置越靠前,执行顺序越靠后

二、通过代码验证插件执行顺序

2.1、验证不同对象拦截器的执行顺序

验证入口为 Executor#query ,准备查询接口,同时准备4个插件拦截器,并将四个插件拦截器配置到 mybatis-config.xml 配置文件 <plugins> 标签中(顺序无所谓)

2.1.1、查询接口忽略

2.1.2、四个插件拦截器

243d93273a2e2e7949f62e9ce5a3d006.png

如上述定义了四个插件拦截器,分别对应四种对象的拦截器,以 Executor 拦截器为例 ,代码如下:

2e330bb844421c5edcae7690b5ac0420.png

通过打印日志,查看执行顺序,其他拦截器相同

2.1.3、在配置文件中配置

10017c7b20862189ad4ebfcf08dc08a1.png

如上述配置,为了验证配置顺序无关性,特地打乱其配置顺序。

2.1.4、执行结果

262154b2b88fabedc247dae5752021f0.png

执行结果正如我们所预料的一样,执行顺序Mybatis 已经固化了。

2.2、验证多个同对象拦截器的执行顺序

Executor#query 为例

2.2.1、创建多个 Executor 拦截器,并拦截同一个方法 Executor#query

d76cfd30c237c6b74ac6bd9168bec659.png

其中ExecutorQueryPlugin1代码如下:

756468b8c775cc640b61a372ead9aa40.png

2.2.2、配置文件配置

1b64d7bb9d6b8758176573aeebe0a5ed.png

如上述配置所示,拦截器配置顺序为 2,1,3,通过上述结论可以得出,其执行顺序为:3,1,2----2,1,3

2.2.3、测试结果

控制台打印信息如下:

0e594d53990bb2ee831bf2f914502773.png

三、总结

Mybatis 插件的执行顺序有两种

1、不同拦截对象执行顺序,如下:

Executor` -> `StatementHandler` -> `ParameterHandler` -> `ResultSetHandler

2、拦截相同对象执行顺序,取决于 mybatis-config.xml 中 <plugin> 配置顺序,越靠后,优先级越高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值