MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。
MyBatis 拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动MyBatis 固有的逻辑。
默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
对于拦截器MyBatis 为我们提供了一个Interceptor接口,通过实现该接口就可以定义我们自己的拦截器。我们来看一下这个接口的定义:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
我们可以看到在该接口中一共有三个方法。
- plugin方法时拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理。当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法,当然也可以调用其他方法。setProperties方法是用于在Mybatis配置文件中指定一些属性的。
- 定义自己的Interceptor最重要的是要实现plugin方法和intercept方法,在plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象。而intercept方法就是要进行拦截的时候要执行的方法。
- 对于plugin方法而言,其实MyBatis已经为我们提供了一个实现。Mybatis中有一个叫做Plugin的类,里面有一个静态方法wrap(Object target,Interceptor interceptor),通过该方法可以决定要返回的对象是目标对象还是对应的代理。
- 对于实现自己的Interceptor而言有两个很重要的注解,一个是@Intercepts,其值是一个@Signature数组。@Intercepts用于表明当前的对象是一个Interceptor,而@Signature则表明要拦截的接口、方法以及对应的参数类型。
实现自己的拦截器
1.实现Interceptor接口
@Intercepts({@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MyInterceptor implements Interceptor {
/**
* @param invocation{ 代理对象,被监控方法对象,当前被监控方法运行时需要实参 }
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("被拦截方法执行之前,做的辅助服务");
Object obj = invocation.proceed();//执行被拦截方法
System.out.println("被拦截方法执行之后,做的辅助服务");
return obj;
}
/**
* 如果被拦截对象所在的类有实现接口,就为当前拦截对象生成一个代理对象
* 如果没有指定接口,这个对象之后行为就不会被代理操作
*
* @param target 表示被拦截的对象,针对当前,应该Executor接口实例对象
* @return
*/
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
2.在MyBatis核心配置文件注册自定义拦截器
<plugins>
<plugin interceptor="com.tamty.utils.MyInterceptor"></plugin>
</plugins>