一、实现:
1、实现Interceptor接口:
2、配置签名注解:
案例:
@Intercepts({@Signature( type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} )}) public class PageHelper implements Interceptor{}二、原理:
插件通过动态代理机制,可以介入四大对象的任何一个方法的执行;
•Executor(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) •ParameterHandler(getParameterObject, setParameters) •ResultSetHandler(handleResultSets, handleOutputParameters) •StatementHandler(prepare, parameterize, batch, update, query)
三、详解;
1、拦截器介绍:
public interface Interceptor { Object intercept(Invocation var1) throws Throwable; Object plugin(Object var1); //传递插件参数 void setProperties(Properties var1); }(1)void setProperties(Properties var1);
这个方法用来传递插件的参数,可以通过参数来改变插件的行为
<plugins> <plugin interceptor= ” tk.mybatis . simple.plugin . XXXInterceptor " > < property 口ame = ” propl ” value =” value l ”/> <property 口ame = ” prop2 ” value =” value2 ”/ 〉 </plugin> </plugins>
(2)Object plugin(Object target);
target:拦截器拦截的对象;
在创建被拦截的接口实现类时被调用;
接口实现:(通过wrap()方法会自动判断拦截器的签名和被拦截对象的接口是否匹配,只有匹配会通过Java动态代理拦截目标对象)
@Override public Object plugin(Object target) { return Plugin .wrap(target , this) ; }
(3) Object intercept(Invocation var1) throws Throwable;
Invocation提供很多方法:
getTarget ():获取当前被拦截的对象;
getMethod():可以获取当前被拦截的方法;
getArgs ():可以返回被拦截方法中的参数。
invocation.proceed():可以执行被拦截对象真正的方法, proceed()方法实际上执行了method.invoke(target,args )方法;
2、执行顺序:
当配置多个拦截器时, MyBatis 会遍历所有拦截器,按顺序执行拦截器的plugin方法,被拦截的对象就会被层层代理。在执行拦截对象的方法时,会一层层地调用拦截器,拦截器通过invocation . proceed ()调用下一层的方法,直到真正的方法被执行。方法执行的结果会从最里面开始向外一层层返回,所以如果存在按顺序配置的A 、B 、C 三个签名相同的拦截器, MyBaits 会按照C>B>A>target.proceed()>A>B>C 的顺序执行。
3、签名;
@ Intercepts注解中的属性是一个@ Signature (签名)数组;
@Signature 注解包含以下三个属性。 type : 设置拦截的接口,可选值是前面提到的4 个接口。 method : 设置拦截接口中的方法名, 可选值是前面4 个接口对应的方法,需要和接口匹配。 args : 设置拦截方法的参数类型数组, 通过方法名和参数类型可以确定唯一一个方法