源码解析mybatis拦截器的运行原理

文章详细解析了MyBatis框架中Interceptor的使用,重点讨论了如何在`Executor`接口的`query`方法中通过注解进行拦截,以及`InterceptorChain`、`Plugin`和动态代理在配置文件中的作用。
摘要由CSDN通过智能技术生成

boundSql = ms.getBoundSql(parameter);

cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);

} else {

cacheKey = (CacheKey)args[4];

boundSql = (BoundSql)args[5];

}

System.out.println(“Interceptor1”);

List resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);

return resultList;

}

}

@Intercepts({@Signature(

type = Executor.class,

method = “query”,

args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}

), @Signature(

type = Executor.class,

method = “query”,

args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}

)})

public class Interceptor2 implements Interceptor {

@Override

public Object intercept(Invocation invocation) throws Throwable {

Object[] args = invocation.getArgs();

MappedStatement ms = (MappedStatement)args[0];

Object parameter = args[1];

RowBounds rowBounds = (RowBounds)args[2];

ResultHandler resultHandler = (ResultHandler)args[3];

Executor executor = (Executor)invocation.getTarget();

CacheKey cacheKey;

BoundSql boundSql;

if (args.length == 4) {

boundSql = ms.getBoundSql(parameter);

cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);

} else {

cacheKey = (CacheKey)args[4];

boundSql = (BoundSql)args[5];

}

System.out.println(“Interceptor2”);

List resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);

return resultList;

}

}

其他配置和一文看懂mybatis底层运行原理解析这篇里面的一样。

首先我们看获取SqlSession的方法

不多做解释,直接看到org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource方法的74行:

继续往下看 newExecutor 方法的579行:

继续看org.apache.ibatis.plugin.InterceptorChain#pluginAll方法:

可以看到这里会去遍历 interceptors 这个集合。那么 interceptors 这个属性是什么时候初始化的呢?

是在构造 SqlSessionFactory 时初始化的,继续往下 会看到 org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration 这个方法

上图中可以看到初始化 mybatis-config.xml 时,会解析其中的plugin属性,然后放到 org.apache.ibatis.plugin.InterceptorChain#interceptors 中。

继续看 interceptor 主流程的执行:

上图中可以看到 Interceptor 接口中的 plugin 方法都有一个默认实现:org.apache.ibatis.plugin.Plugin#wrap 方法

继续看 getSignatureMap 方法:

这段代码主要就是获取 Interceptor 实现类上的注解信息,结合 Interceptor1 上注解可以知道,最后 signatureMap 中存储的信息就是key为 Executor.class,value为Executor接口中的2个query方法。

继续看 getAllInterfaces 方法:

代码中能看到会循环遍历type类的父接口,然后判断signatureMap是否包含此类,结果会返回signatureMap中key包含的接口类,也就是Executor接口了。

继续往下看 Proxy.newProxyInstance 方法:

这行代码就用到了动态代理设计模式了,不熟悉的同学可以先去看看我的白话解析动态代理设计模式

结果就是会根据mybatis-config.xml中配置的拦截器数量来生成代理类,最后都会去调用org.apache.ibatis.plugin.Plugin#invoke方法

上图中就会去执行自定义Interceptor中的 intercept 方法了。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

1200页Java架构面试专题及答案

小编整理不易,对这份1200页Java架构面试专题及答案感兴趣劳烦帮忙转发/点赞

百度、字节、美团等大厂常见面试题

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
cgfQoUm-1713751594270)]

[外链图片转存中…(img-542YEDzD-1713751594270)]

百度、字节、美团等大厂常见面试题

[外链图片转存中…(img-YDdDhUE0-1713751594270)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值