1. 程式人生 > 實用技巧 >mybatis外掛(攔截器)

mybatis外掛(攔截器)

1、作用

可以在sql執行前後 結果對映 引數解析階段做攔截處理(AOP)

如:日誌列印 效能監控等

2、攔截的4個物件

Execute StatementHandle ParameterHandle ResultHandle

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed),主要用於sql重寫。
  • ParameterHandler (getParameterObject, setParameters),用於引數處理。
  • ResultSetHandler (handleResultSets, handleOutputParameters),用於結果集二次處理。
  • StatementHandler (prepare, parameterize, batch, update, query),用於jdbc層的控制。

3、使用

定義哪個物件 哪個方法進行攔截

如:plugin方法返回代理物件

4、原理

具體的方法定義可以參見每個類方法的簽名,這裡就不詳細展開了。這四個類被建立後不是直接返回,而是創執行了interceptorChain.pluginAll(parameterHandler)才返回。如下所示:

pluginAll最終呼叫每個攔截器的plugin方法,返回代理物件,如果有多個攔截器,就會一層層代理。

//Configuration 中
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
  ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
  parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
  return parameterHandler;
}
​
public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
                      ResultHandler resultHandler, BoundSql boundSql) {
  ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
  resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
  return resultSetHandler;
}
​
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
  StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
  statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
  return statementHandler;
}
​
public Executor newExecutor(Transaction transaction) {
  return newExecutor(transaction, defaultExecutorType);
}
​
// Execute預設使用SimpleExecutor public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Executor executor; if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor
(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (cacheEnabled) { executor = new CachingExecutor(executor); } executor = (Executor) interceptorChain.pluginAll(executor); return executor; }

5、總結

使用的設計模式:代理模式、責任鏈模式

參考:

https://www.cnblogs.com/chenpi/p/10498921.htm

https://www.cnblogs.com/zhjh256/p/11516878.html

https://my.oschina.net/u/4365042/blog/3344199l