mybatis插件原理

mybatis的插件原理可参考博文,http://blog.csdn.net/hupanfeng/article/details/9247379,本文可作为补充。

1mybatis的自定义插件,需要实现Interceptor接口,里面有三个接口:

Object intercept(Invocation var1) throws Throwable;
Object plugin(Object var1);
void setProperties(Properties var1);

调用顺序分别是:setProperties(xxx) => plugin(xx), => intercept(xxx);第一个是设置参数,第二个是生成动态代理(为考虑性能,一般会判断是否当前信息是否是当前插件需要拦截的动作),第三个是执行(额,也就是自定义插件的具体内容需要写在这里)。


2InterceptorChain里保存了所有的拦截器,他有一个pluginAll方法用来创建已注册的插件的动态代理,

mybatis插件原理_第1张图片

该方法的其中一条调用路径(执行一条SQL时,即使是执行一条SQL这样简单的任务,pluginAll也可能会被调用很多次)如下图所示:

mybatis插件原理_第2张图片

InterceptorChain里注册的插件interceptors是在解析XML配置时注入的,

mybatis插件原理_第3张图片


3Object plugin(Object var1);

假设原始对象的类型是T,被拦截的方法是m.

该方法返回插件的代理对象(是JVM临时生成的一个继承T的类(如,$Proxy35),同时传入一个InvocationHandler对象(ProxyWrapper)或者原始对象,该类有三个成员,targetinterceptorsignatureMap

target是下一层插件的代理对象或原始对象(你看,这就构成了代理链);

interceptor是当前层次的插件;

signatureMap保存了哪些类(原始对象对应的类)的哪些方法被拦截


4Object intercept(Invocation var1)

参数传入的是代理链接上的下一个插件的相关参数,Invocation同样包含三个成员,targetmethodargs

target是下一级插件的代理对象或原始对象,method被拦截的方法,args对应参数。

末尾有一句


如果target是插件的话,触发插件的执行(即经历代理对象的invoke(xx)=> ProxyWrapperinvoke(xxx)=>插件的intercept(xxx)),如此循环;

如果target是目标类的话,那么调用被拦截的方法。


5、最外一层的代理对象的invoke方法何时被调用呢?

最外层的代理对象,因为继承了T,所以可以显式调用方法m,从而转到代理对象的invoke方法,进而转到ProxyWrapperinvoke方法里.

例如:

mybatis插件原理_第4张图片

handler是个代理对象时,handler.preparexxx)的调用会转成代理对象(如类名为”$Proxy35”的对象)的invoke方法的调用,再转到ProxyWrapperinvoke方法里,进而转到插件的intercept(xx)里面,你看进入4的循环了。


6ProxyWrapperinvoke方法

这里,如果被调用的方法是被拦截的方法,那么调用插件的intercept(xxx)方法,并结束;否则呢,调用原始对象的被拦截方法。

mybatis插件原理_第5张图片




你可能感兴趣的:(JAVA,开源工具,mybatis)