MyBatis 允許在已映射語句執(zhí)行過程中的某一點進行攔截調(diào)用。
MyBatis 攔截器設計的一個初衷就是為了供用戶在某些時候可以實現(xiàn)自己的邏輯而不必去動MyBatis 固有的邏輯。
默認情況下,MyBatis 允許使用插件來攔截的方法調(diào)用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
對于攔截器MyBatis 為我們提供了一個Interceptor接口,通過實現(xiàn)該接口就可以定義我們自己的攔截器。我們來看一下這個接口的定義:
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
Object plugin(Object target);
void setProperties(Properties properties);
}
我們可以看到在該接口中一共有三個方法。
- plugin方法時攔截器用于封裝目標對象的,通過該方法我們可以返回目標對象本身,也可以返回一個它的代理。當返回的是代理的時候我們可以對其中的方法進行攔截來調(diào)用intercept方法,當然也可以調(diào)用其他方法。setProperties方法是用于在Mybatis配置文件中指定一些屬性的。
- 定義自己的Interceptor最重要的是要實現(xiàn)plugin方法和intercept方法,在plugin方法中我們可以決定是否要進行攔截進而決定要返回一個什么樣的目標對象。而intercept方法就是要進行攔截的時候要執(zhí)行的方法。
- 對于plugin方法而言,其實MyBatis已經(jīng)為我們提供了一個實現(xiàn)。Mybatis中有一個叫做Plugin的類,里面有一個靜態(tài)方法wrap(Object target,Interceptor interceptor),通過該方法可以決定要返回的對象是目標對象還是對應的代理。
- 對于實現(xiàn)自己的Interceptor而言有兩個很重要的注解,一個是@Intercepts,其值是一個@Signature數(shù)組。@Intercepts用于表明當前的對象是一個Interceptor,而@Signature則表明要攔截的接口、方法以及對應的參數(shù)類型。
實現(xiàn)自己的攔截器
1.實現(xiàn)Interceptor接口
@Intercepts({@Signature(
type = Executor.class,
method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class MyInterceptor implements Interceptor {
/**
* @param invocation{ 代理對象,被監(jiān)控方法對象,當前被監(jiān)控方法運行時需要實參 }
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("被攔截方法執(zhí)行之前,做的輔助服務");
Object obj = invocation.proceed();//執(zhí)行被攔截方法
System.out.println("被攔截方法執(zhí)行之后,做的輔助服務");
return obj;
}
/**
* 如果被攔截對象所在的類有實現(xiàn)接口,就為當前攔截對象生成一個代理對象
* 如果沒有指定接口,這個對象之后行為就不會被代理操作
*
* @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>