Mybatis系列之七 Interceptor

如题所述

第1个回答  2022-06-14

Mybatis拦截器采用了责任链模式。这里简单讲一下责任链模式的概念,如果想了解更多的话,可以去百度,google搜索责任链即可。
责任链模式:使多个对象都有处理请求的机会,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象串成一条链,并沿着这条链一直传递该请求,直到有对象处理它为止。

在我们讲Mybatis的Interceptor之前,先看一个小例子,作用是去拦截Executor接口的 List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4) ,每当执行这个方法时,输出一个字符串到控制台 “拦截到了mybatis的BaseExecutor中的方法”

下面是配置好了Interceptor之后的执行结果,可以看到在控制台中已经输出两条自定义的字符串了。那么我们就来看看Mybatis是怎么来实现拦截器的。

例子中的自定义拦截器CustomInterceptor实现了Mybatis定义的Interceptor接口,我们先看一下它的定义。

看到上面的定义,主要是3部分,一个是拦截器属性的设置(这个就pass了),还有就是注册与具体业务逻辑实现。
我们先看看plugin()方法用在了哪儿?我们发现其实只有InterceptorChain链中的pluginAll()这个方法调用了它。看实现是把入参target利用拦截器包了一层,然后返回包装后的对象。

再看看InterceptorChain中的pluginAll()都有什么地方调用了,换个说法就是Mybatis在哪些地方支持加拦截器?ok,我们看到在Configuration中创建帮助实例化ParameterHandler,ResultSetHandler,StatementHandler,Executor类时都支持拦截器。

看完了调用链,我们再看看具体怎么实现这个plugin方法。其实Mybatis已经给我们提供了一个工具类Plugin来帮助我们简单实现。
再看一下我们例子中plugin()方法的实现,是借助了Plugin类的wrap()方法。其实现原理也比较简单,首先先根据我们自定义拦截器注解的配置解析出我们需要拦截哪个类的哪个方法,然后再对target参数生成一个代理对象返回。

我们可以看到代理对象是 new Plugin(target, interceptor, signatureMap)); 。可以看到 在invoke方法中调用了自定义拦截器的interceptor的方法

至此,关于Mybatis拦截器的实现就结束了,有问题的小伙伴欢迎交流。

相似回答