激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

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

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)。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 蜜桃久久一区二区三区 | 鲁久久| 久夜tv| 夜夜夜精品视频 | xnxx 日本19 | 久久我不卡 | 日韩视频一区二区在线观看 | 特级无码毛片免费视频尤物 | 国产精品毛片va一区二区三区 | 日韩av有码在线 | 精国产品一区二区三区 | 成人毛片100部 | 亚洲码无人客一区二区三区 | 日本教室三级在线看 | av影院在线 | 国产欧美日韩在线播放 | 久久久久久久久久久久网站 | 狠狠ri| 国产精品自拍啪啪 | 亚洲国产精品久久久久婷婷老年 | 国产影视| 91精品中文字幕 | 国产乱色精品成人免费视频 | 精品国产一区二区亚洲人成毛片 | 日日狠狠久久偷偷四色综合免费 | 沉沦的校花奴性郑依婷c到失禁 | 在线看免费观看av | 日本在线国产 | 欧美1| 进去了(高h) | 99在线精品视频免费观看20 | 91美女视频在线观看 | 国产精品一区二区三区在线 | 麻豆一二区 | 91视频久久 | 伊人yinren22综合网色 | xnxx18日本| 色综合网在线观看 | 亚洲精品一区中文字幕 | 国产午夜电影在线观看 | 亚洲一区二区三区高清 |