一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|

服務器之家 - 編程語言 - JAVA教程 - java MyBatis攔截器Inteceptor詳細介紹

java MyBatis攔截器Inteceptor詳細介紹

2020-07-01 11:45服務器之家 JAVA教程

這篇文章主要介紹了java MyBatis攔截器Inteceptor詳細介紹的相關資料,需要的朋友可以參考下

有許多java初學者對于MyBatis攔截器Inteceptor不是很了解,在這里我來為各位整理下篇關于java中MyBatis攔截器Inteceptor詳解,

本文主要分析MyBatis的插件機制,實際就是Java動態代理實現的責任鏈模式實現。

根據官方文檔。Mybatis只允許攔截以下方法,這個決定寫攔截器注解簽名參數。

 代碼如下 

?
1
2
3
4
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)

攔截處理的源碼如下,其中interceptorChain.pluginAll(..)即為織入自定義攔截器:

代碼如下 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/* org.apache.ibatis.session.Configuration類中方法 */
public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
  ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
  /* 攔截ParameterHandler*/
  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 = (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 = (StatementHandler) interceptorChain.pluginAll(statementHandler);
  return statementHandler;
}
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 = (Executor) interceptorChain.pluginAll(executor);
 return executor;
}

實現一個自定義攔截器只需實現Interceptor接口即可,大致代碼如下:

 代碼如下 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* 注解表明要攔截哪個接口的方法及其參數 */
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class YourInterceptor implements Interceptor{
 public Object intercept(Invocation invocation) throws Throwable{
  doSomeThing();
  /* 注:此處實際上使用Invocation.proceed()方法完成interceptorChain鏈的遍歷調用(即執行所有注冊的Interceptor的intercept方法),到最終被代理對象的原始方法調用 */
  return invocation.proceed();
 }
  /*生成成對目標target的代理,而@Intercepts的注解是在Plugin.wrap中用到*/
 @Override
 public Object plugin(Object target){
   /* 當目標類是StatementHandler類型時,才包裝目標類,不做無意義的代理 */
  return (target instanceof StatementHandler)?Plugin.wrap(target, this):target;
 }
  /*用于設置自定義的攔截器配置參數*/
 @Override
 public void setProperties(Properties properties){
 }
}

其中,攔截調用的代碼均在Plugin.wrap中:

代碼如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/* org.apache.ibatis.plugin.Plugin類 */
public class Plugin implements InvocationHandler {
 /* 省略代碼... */
 public static Object wrap(Object target, Interceptor interceptor) {
  /* 此處即為獲取Interceptor的注解簽名 */
  Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
  Class<?> type = target.getClass();
  /* 獲取攔截目標類相匹配的接口 */
  Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
  if (interfaces.length > 0) {
   /* 使用jdk動態代理 */
   return Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap));
  }
  return target;
 }
 /* 攔截目標類的所有方法的執行都會變為在此執行 */
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
   Set<Method> methods = signatureMap.get(method.getDeclaringClass());
   if (methods != null && methods.contains(method)) {
    /* 執行攔截器方法 */
    return interceptor.intercept(new Invocation(target, method, args));
   }
   return method.invoke(target, args);
  } catch (Exception e) {
   throw ExceptionUtil.unwrapThrowable(e);
  }
 }
 /* 省略代碼... */
}

可以看到MyBatis的攔截器設計核心代碼還是比較簡單的,但是足夠靈活。實際使用時注意,不做無意義的代理(Plugin.wrap)。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 色综合色狠狠天天久久婷婷基地 | 9久久9久久精品 | 99re这里只有精品视频在线观看 | 小小水蜜桃视频高清在线播放 | 青青在线香蕉国产精品 | 日产精品卡一卡2卡三卡乱码工厂 | 日本福利片国产午夜久久 | 亚洲激情偷拍 | 国产男女爱视频在线观看 | 免费一级片在线观看 | 无人区在线观看免费观看 | 99久久精品免费看国产四区 | 日产精品一卡2卡三卡4乱码久久 | 九九九久久久 | 停停色 | 国产香蕉一区二区精品视频 | 99网站在线观看 | 99精品久久精品一区二区小说 | 4p高h三男一女 | 校草让我脱了内裤给全班看 | 91嫩草私人成人亚洲影院 | 日本videos有奶水的hd | 忘忧草秋观看未满十八 | 美女操穴视频 | 加勒比京东热 | 色小妹在线 | 蘑菇香蕉茄子绿巨人丝瓜草莓 | 亚洲高清国产拍精品动图 | 国产日韩精品一区二区在线观看播放 | 日韩视频一区二区三区 | 免费观看欧美成人h | 日本久久免费大片 | 91看片淫黄大片.在线天堂 | 国产精品nv在线观看 | 色综色 | 小SAO货边洗澡边CAO你动漫 | 亚洲国产精品日韩高清秒播 | 四虎传媒| 免费特黄一区二区三区视频一 | 欧美三级不卡在线观线看高清 | chinese男gay|