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

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美久在线观看在线观看 | 国产va免费精品高清在线观看 | 校花在公车上被内射好舒 | 免费黄色网站视频 | 免费观看俄罗斯特黄特色 | 鬼吹灯之天星术免费观看 | 国内自拍网红在线自拍综合 | 男女肉文高h | 精品免费视在线观看 | 日本xxxxxx片免费播放18 | 楚乔传第二部全60集免费观看 | 1024免费福利永久观看网站 | 日韩a无吗一区二区三区 | 亚洲AV久久无码精品蜜桃 | 99视频久久 | 四虎影视在线观看永久地址 | 波多野结衣护士 | 男人捅女人动漫 | 波多洁野衣一二区三区 | 精品国产自在现线拍400部 | 欧美一级专区免费大片俄罗斯 | 美女的隐私视频免费看软件 | 星空无限传媒视频在线观看视频 | 国产一区二区三区欧美 | 国产1区2区在线观看 | 亚洲毛片基地4455ww | 啊好爽视频 | 王雨纯 羞羞 | 免费lulu网站 | 久久久久久久久女黄 | 欧美成人tv在线观看免费 | 国产精品美女福利视频免费专区 | 欧美日韩国产成人综合在线影院 | 国产一区二区三区欧美精品 | h肉动漫在线视频无修无遮挡 | 亚洲AV国产福利精品在现观看 | 欧美一区高清 | 亚洲品质自拍视频 | 男人操女人动图 | 翁息肉小说老扒 | 毛片一区二区三区提莫影院 |