最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java MyBatis攔截器Inteceptor詳細(xì)介紹

 更新時(shí)間:2016年11月07日 11:28:12   投稿:lqh  
這篇文章主要介紹了java MyBatis攔截器Inteceptor詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下

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

本文主要分析MyBatis的插件機(jī)制,實(shí)際就是Java動(dòng)態(tài)代理實(shí)現(xiàn)的責(zé)任鏈模式實(shí)現(xiàn)。

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

 代碼如下 

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

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

代碼如下 

/* 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;
}

實(shí)現(xiàn)一個(gè)自定義攔截器只需實(shí)現(xiàn)Interceptor接口即可,大致代碼如下:

 代碼如下 

/* 注解表明要攔截哪個(gè)接口的方法及其參數(shù) */
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class YourInterceptor implements Interceptor{
 public Object intercept(Invocation invocation) throws Throwable{
  doSomeThing();
  /* 注:此處實(shí)際上使用Invocation.proceed()方法完成interceptorChain鏈的遍歷調(diào)用(即執(zhí)行所有注冊的Interceptor的intercept方法),到最終被代理對象的原始方法調(diào)用 */
  return invocation.proceed();
 }
  /*生成成對目標(biāo)target的代理,而@Intercepts的注解是在Plugin.wrap中用到*/
 @Override
 public Object plugin(Object target){
   /* 當(dāng)目標(biāo)類是StatementHandler類型時(shí),才包裝目標(biāo)類,不做無意義的代理 */
  return (target instanceof StatementHandler)?Plugin.wrap(target, this):target;
 }
  /*用于設(shè)置自定義的攔截器配置參數(shù)*/
 @Override
 public void setProperties(Properties properties){
 }
}

其中,攔截調(diào)用的代碼均在Plugin.wrap中:

代碼如下

/* 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();
  /* 獲取攔截目標(biāo)類相匹配的接口 */
  Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
  if (interfaces.length > 0) {
   /* 使用jdk動(dòng)態(tài)代理 */
   return Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap));
  }
  return target;
 }
 /* 攔截目標(biāo)類的所有方法的執(zhí)行都會(huì)變?yōu)樵诖藞?zhí)行 */
 @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)) {
    /* 執(zhí)行攔截器方法 */
    return interceptor.intercept(new Invocation(target, method, args));
   }
   return method.invoke(target, args);
  } catch (Exception e) {
   throw ExceptionUtil.unwrapThrowable(e);
  }
 }
 /* 省略代碼... */
}

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

相關(guān)文章

  • java中l(wèi)ambda表達(dá)式的分析與具體用法

    java中l(wèi)ambda表達(dá)式的分析與具體用法

    這篇文章主要給大家介紹了關(guān)于java中l(wèi)ambda表達(dá)式具體用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Idea如何配置Maven才能優(yōu)先從本地倉庫獲取依賴(親測方法有效)

    Idea如何配置Maven才能優(yōu)先從本地倉庫獲取依賴(親測方法有效)

    對于Idea怎么配置Maven才能優(yōu)先從本地倉庫獲取依賴,網(wǎng)上說法有很多種,都不太靠譜,最終都沒有效果,最好的解決方法是通過修改maven配置文件settings.xml,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧
    2023-10-10
  • mybatis通過XML的方式拼接動(dòng)態(tài)sql

    mybatis通過XML的方式拼接動(dòng)態(tài)sql

    動(dòng)態(tài)SQL是一種在運(yùn)行時(shí)構(gòu)造和執(zhí)行SQL語句的技術(shù),這篇文章主要為大家介紹了mybatis如何通過XML的方式拼接動(dòng)態(tài)sql,有需要的小伙伴可以參考一下
    2024-12-12
  • Java編程獲取經(jīng)緯度之間距離的方法

    Java編程獲取經(jīng)緯度之間距離的方法

    這篇文章主要介紹了Java編程獲取經(jīng)緯度之間距離的方法,涉及Java數(shù)學(xué)運(yùn)算的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-11-11
  • SpringBoot項(xiàng)目實(shí)現(xiàn)分布式日志鏈路追蹤

    SpringBoot項(xiàng)目實(shí)現(xiàn)分布式日志鏈路追蹤

    這篇文章主要給大家介紹了Spring Boot項(xiàng)目如何實(shí)現(xiàn)分布式日志鏈路追蹤,文中通過代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • 在Java中操作Zookeeper的示例代碼詳解

    在Java中操作Zookeeper的示例代碼詳解

    這篇文章主要介紹了在Java中操作Zookeeper的示例代碼詳解,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 使用MapStruct進(jìn)行Java Bean映射的方式

    使用MapStruct進(jìn)行Java Bean映射的方式

    MapStruct是一個(gè)用于JavaBean映射的注解處理器,它通過注解生成類型安全且性能優(yōu)異的映射代碼,避免手動(dòng)編寫重復(fù)的樣板代碼,主要特性包括類型安全、高性能、簡潔和可定制性,使用步驟包括定義映射接口、創(chuàng)建源類和目標(biāo)類、生成映射代碼并調(diào)用映射方法
    2025-02-02
  • 深入理解Java8新特性之接口中的默認(rèn)方法和靜態(tài)方法

    深入理解Java8新特性之接口中的默認(rèn)方法和靜態(tài)方法

    從Java8開始,程序允許在接口中包含帶有具體實(shí)現(xiàn)的方法,使用default修飾,這類方法就是默認(rèn)方法。默認(rèn)方法在接口中可以添加多個(gè),并且Java8提供了很多對應(yīng)的接口默認(rèn)方法,接下來讓我們一起來看看吧
    2021-11-11
  • 詳解Java回調(diào)的原理與實(shí)現(xiàn)

    詳解Java回調(diào)的原理與實(shí)現(xiàn)

    回調(diào)函數(shù),顧名思義,用于回調(diào)的函數(shù)?;卣{(diào)函數(shù)只是一個(gè)功能片段,由用戶按照回調(diào)函數(shù)調(diào)用約定來實(shí)現(xiàn)的一個(gè)函數(shù)?;卣{(diào)函數(shù)是一個(gè)工作流的一部分,由工作流來決定函數(shù)的調(diào)用(回調(diào))時(shí)機(jī)。
    2017-03-03
  • SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)流程詳解

    SpringBoot集成ShedLock實(shí)現(xiàn)分布式定時(shí)任務(wù)流程詳解

    ShedLock是一個(gè)鎖,官方解釋是他永遠(yuǎn)只是一個(gè)鎖,并非是一個(gè)分布式任務(wù)調(diào)度器。一般shedLock被使用的場景是,你有個(gè)任務(wù),你只希望他在單個(gè)節(jié)點(diǎn)執(zhí)行,而不希望他并行執(zhí)行,而且這個(gè)任務(wù)是支持重復(fù)執(zhí)行的
    2023-02-02

最新評論

尉犁县| 泽库县| 喜德县| 旌德县| 梁平县| 丽江市| 平泉县| 和静县| 越西县| 玉环县| 旌德县| 德保县| 台北县| 松潘县| 隆尧县| 建昌县| 太仓市| 金塔县| 兴国县| 八宿县| 吉林省| 龙门县| 正宁县| 阳江市| 隆昌县| 广德县| 镶黄旗| 宾川县| 芒康县| 天台县| 克拉玛依市| 商都县| 宁武县| 柯坪县| 毕节市| 郁南县| 介休市| 永胜县| 界首市| 黄浦区| 武汉市|