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> 配置顺序,越靠后,优先级越高。

在使用maven的mybatis-generator-maven-plugin插件自动生成实体映射文件时,我们首先需要在maven的pom.xml文件中配置插件。 在<build>标签下,添加如下代码: ``` <plugins> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.4.0</version> <dependencies> <!-- 添加数据库驱动依赖 --> </dependencies> <configuration> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> </plugin> </plugins> ``` 接下来,在项目的根目录下执行以下命令生成实体映射文件: ``` mvn mybatis-generator:generate ``` 执行完毕后,插件会根据配置信息,在项目的src/main/java目录下生成对应的实体类、mapper接口和xml映射文件。 在配置插件时,可以设置数据库连接信息、需要生成的表名、生成的实体类和映射文件的位置等。具体的配置信息可以参考官方文档。 生成的实体类对应数据库中的表结构,各个字段通过对应的get和set方法来访问。生成的mapper接口定义了对应的数据库操作方法,通过调用这些方法可以对数据库进行增删改查操作。生成的xml映射文件定义了实体类和数据库表之间的映射关系,通过该文件可以实现对象和表的相互转换。 通过使用maven的mybatis-generator-maven-plugin插件,我们可以简化开发人员编写实体映射文件的工作,提高开发效率和代码质量。同时,插件的配置灵活多样,可以根据项目的实际需求进行定制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值