Mybatis插件編寫:
- 1、編寫Interceptor的實現類
- 2、使用@Intercepts注解完成插件簽名
- 3、將寫好的插件注冊到全局配置文件中
/**
* 完成插件簽名:
* 告訴MyBatis當前插件用來攔截哪個對象的哪個方法
*/
@Intercepts(
{
@Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
})
public class MyFirstPlugin implements Interceptor{
/**
*
* 攔截目標對象的目標方法的執行
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("MyFirstPlugin...intercept:"+invocation.getMethod());
//動態的改變一下sql運行的參數:以前1號員工,實際從數據庫查詢2號員工
Object target = invocation.getTarget();
System.out.println("當前攔截到的對象:"+target);
//拿到:StatementHandler==>ParameterHandler===>parameterObject
//拿到target的元數據
MetaObject metaObject = SystemMetaObject.forObject(target);
Object value = metaObject.getValue("parameterHandler.parameterObject");
System.out.println("sql語句用的參數是:"+value);
//修改完sql語句要用的參數
metaObject.setValue("parameterHandler.parameterObject", 2);
//執行目標方法
Object proceed = invocation.proceed();
//返回執行后的返回值
return proceed;
}
/**
*
*包裝目標對象的:為目標對象創建一個代理對象
*/
@Override
public Object plugin(Object target) {
// TODO Auto-generated method stub
//我們可以借助Plugin的wrap方法來使用當前Interceptor包裝我們目標對象
System.out.println("MyFirstPlugin...plugin:mybatis將要包裝的對象"+target);
Object wrap = Plugin.wrap(target, this);
//返回為當前target創建的動態代理
return wrap;
}
/**
*
*將插件注冊時 的property屬性設置進來
*/
@Override
public void setProperties(Properties properties) {
// TODO Auto-generated method stub
System.out.println("插件配置的信息:"+properties);
}
}
在全局配置文件中注冊:
<!-- mybatis-config.xml -->
<plugins>
<plugin interceptor="org.mybatis.example.MyFirstPlugin">
<property name="someProperty" value="100"/>
</plugin>
</plugins>
插件是用來包裝四大對象,攔截指定的方法:
-
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
-
ParameterHandler (getParameterObject, setParameters)
-
ResultSetHandler (handleResultSets, handleOutputParameters)
-
StatementHandler (prepare, parameterize, batch, update, query)
四大對象在執行增刪改查方法的過程中的作用:
1)、Mappe代理對象調用DefaultSqlSession的增刪改查方法,DefaultSqlSession實際上是調用Executor的update(增刪改)、query;
2)、Executor會創建一個StatementHandler對象(同時也會創建出ParameterHandler和ResultSetHandler)
3)、Executor使用StatementHandler預編譯sql,以及使用ParameterHandler來給sql設置參數
4)、Executor調用StatementHandler的增刪改查方法;
5)、ResultSetHandler封裝結果集
在四大對象創建的時候,並不是直接直接返回,都會調用interceptorChain.pluginAll(target):
public Object pluginAll(Object target) {
//使用每一個插件來創建一個代理對象
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}