千家信息网

mybatis多个plugins的执行顺序是怎样的

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,mybatis多个plugins的执行顺序是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、前言在mybatis官网中,有插件一
千家信息网最后更新 2026年11月02日mybatis多个plugins的执行顺序是怎样的

mybatis多个plugins的执行顺序是怎样的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

一、前言

在mybatis官网中,有插件一说 mybatis plugins 如果同时有多个插件,那么他们的执行顺序是怎样的?

二、准备工作、代码准备

1、 项目结构

2、TestDAO

public interface TestDAO {    Test selectById(Integer id);     default void testDefaultMethod(){        System.out.println("===调用接口中的默认方法,用来验证MapperProxy中的isDefaultMethod方法===");    }}

3、Test

@Data@NoArgsConstructor@AllArgsConstructorpublic class Test {    private Integer id;     private String name;}

4、ExamplePlugin

@Intercepts({@Signature(        type= Executor.class, method = "query", args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}        ),        @Signature(                type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}        ),        @Signature(                type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}        ),        @Signature(                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}        )})public class ExamplePlugin implements Interceptor {    @Override    public Object intercept(Invocation invocation) throws Throwable {        System.out.println("==== ExamplePlugin 开始搞事情:" + invocation.getMethod().getName() + "  ====");        return invocation.proceed();    }     @Override    public Object plugin(Object target) {        return Plugin.wrap(target, this);    }     @Override    public void setProperties(Properties properties) {     }}

5、SecondExamplePlugin

@Intercepts({@Signature(        type= Executor.class, method = "query", args={MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}        ),        @Signature(                type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}        ),        @Signature(                type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}        ),        @Signature(                type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}        )})public class SecondExamplePlugin implements Interceptor {    @Override    public Object intercept(Invocation invocation) throws Throwable {        System.out.println("==== SecondExamplePlugin 开始搞事情:" + invocation.getMethod().getName() + "  ====");        return invocation.proceed();    }     @Override    public Object plugin(Object target) {        return Plugin.wrap(target, this);    }     @Override    public void setProperties(Properties properties) {     }}

6、Main

public class Main {     public static SqlSession getSqlSession() throws IOException {        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);        return sqlSessionFactory.openSession();    }     public static void main(String[] args) throws IOException {        TestDAO testDAO = getSqlSession().getMapper(TestDAO.class);        Test test = testDAO.selectById(1); //        testDAO.testDefaultMethod();         //类文件是缓存在java虚拟机中,我们将类文件打印到文件中,便于查看//        generateProxyFile("F:/TestDAOProxy.class");    }     private static void generateProxyFile(String path){        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{TestDAO.class});         try(FileOutputStream fos = new FileOutputStream(path)) {            fos.write(classFile);            fos.flush();            System.out.println("代理类class文件写入成功");        } catch (Exception e) {            System.out.println("写文件错误");        }    }}

7、 TestMapper.xml

                                      id, name          

8、mybatis-confi.xml

                                                                                                                                                                                                             

9、POM

    4.0.0     com.me    mybatis-test    1.0-SNAPSHOT             1.8        1.8                             org.mybatis            mybatis            3.4.6                             org.projectlombok            lombok            1.16.14                             junit            junit            4.12                             mysql            mysql-connector-java            8.0.12             

三、开始探索

1、运行结果

==== SecondExamplePlugin 开始搞事情:query ====
==== ExamplePlugin 开始搞事情:query ====
==== SecondExamplePlugin 开始搞事情:prepare ====
==== ExamplePlugin 开始搞事情:prepare ====
==== SecondExamplePlugin 开始搞事情:setParameters ====
==== ExamplePlugin 开始搞事情:setParameters ====
==== SecondExamplePlugin 开始搞事情:handleResultSets ====
==== ExamplePlugin 开始搞事情:handleResultSets ====

2、疑问:为什么是这样的顺序?

和我们在mybatis-config.xml文件中的顺序相反,为什么?

3、注释掉一个,我们从一个plugin开始debug,看看做了什么

4、如图,在Configuration的四个方法newParameterHandler、newResultSetHandler、newStatementHandler、newExecutor中打上断点

5、debug Main类的main方法

6、我们发现在newExecutor中,被拦住了

这里的interceptorChain是什么东西?我们往上找一找,发现它是在Configuration类中new出来的。它等价于mybatis-config中的

7、我们已经知道interceptorChain是什么了,那么进入它的pluginAll方法

我们可以看到它是遍历interceptors的plugin方法。而interceptors是ArrayList,是有序的。那么在配置文件中,哪个plugin在前,这里它就在前面

8、进入interceptor的plugin方法,发现我们来到了我们自己写的ExamplePlugin类的plugin方法

9、它又继续调用了Plugin的静态方法wrap

1) 第一步获取@Signature注解中的type和method,也就是我们在ExamplePlugin中使用的注解。

2)第二步,用动态代理,生成代理类。其中Plugin作为InvocationHandler

10、UML图

最终Executor不再是原来的类,而是它的代理类。newStatementHandler方法和newResultSetHandler方法的流程,也差不多,最终也是生成代理类。

当Executor、StatementHandler、ParameterHandler、ResultSetHandler执行他们自己的方法时,实际上调用他们的代理类Plugin中的invoke方法。

也就是在interceptor.intercept(new Invocation(target, method, args));这一句中,回到了我们ExamplePlugin的intercept方法

整个流程中Executor的代理。(这里只拿Executor来举例)

四、结论

上面只是代理一次,还记得pluginAll吗?

多个interceptor呢?当然是代理类又被代理了。

所以,后面的将会代理前面的,这也就是为什么SecondExamplePlugin先执行的原因了--越外层的越先执行嘛

多个插件的执行顺序已经明了了,那么插件里面方法的执行顺序呢?

当然是看这些方法什么时候被调用咯

看完上述内容,你们掌握mybatis多个plugins的执行顺序是怎样的的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

方法 代理 事情 顺序 文件 多个 插件 也就是 内容 原因 更多 注解 流程 问题 准备 生成 有序 束手无策 为此 差不多 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技图片 上海卓越科技互联网 A股互联网金融科技公司 科技互联网项目 伴你行互联网科技有限公司 天扬科技互联网广告 成都玖崟互联网科技有限公司乐商圈怎么样 华服互联网科技官网 重庆互联网医院沙龙医盟信息科技 成都互联网科技公司工作好不好 洛阳昕诺飞互联网科技有限公司 广西互联网科技孵化中心 华夏恒生科技与互联网科技 济南有互联网科技公司吗 徐州市互联网科技有限公司 互联网科技公司营业执照怎么办理 互联网领先科技宣传片 九思连强互联网电子科技有限公司 珠海东科互联网科技有限公司 版纳互联网科技选哪家 保险科技 互联网保险 科技互联网产品 致骋互联网科技 互联网科技公司介绍 互联网科技英文翻译 美国互联网前沿科技 农村开互联网科技讲堂 互联网和黑科技的看法 苏州铭阳互联网科技有限公司 科技互联网专业工作会议发言稿
0