成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【深入淺出MyBatis筆記】插件

leon / 584人閱讀

摘要:插件插件接口在中使用插件,我們必須實(shí)現(xiàn)接口。它將直接覆蓋你所攔截對(duì)象原有的方法,因此它是插件的核心方法。插件在對(duì)象中的保存插件的代理和反射設(shè)計(jì)插件用的是責(zé)任鏈模式,的責(zé)任鏈?zhǔn)怯扇ザx的。

插件 1、插件接口

在MyBatis中使用插件,我們必須實(shí)現(xiàn)接口Interceptor。

public interface Interceptor {
  // 它將直接覆蓋你所攔截對(duì)象原有的方法,因此它是插件的核心方法。
  // Intercept里面有個(gè)參數(shù)Invocation對(duì)象,通過它可以反射調(diào)度原來對(duì)象的方法
  Object intercept(Invocation invocation) throws Throwable;

  // 作用是給被攔截對(duì)象生成一個(gè)代理對(duì)象,并返回它。target是被攔截對(duì)象
  Object plugin(Object target);

  // 允許在plugin元素中配置所需參數(shù),方法在插件初始化的時(shí)候就被調(diào)用了一次
  void setProperties(Properties properties);

}
2、插件初始化

插件的初始化是在MyBatis初始化的時(shí)候完成的。

public class XMLConfigBuilder extends BaseBuilder {
  ......
  private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        String interceptor = child.getStringAttribute("interceptor");
        Properties properties = child.getChildrenAsProperties();
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
        interceptorInstance.setProperties(properties);
        configuration.addInterceptor(interceptorInstance);
      }
    }
  }
}

在解析配置文件的時(shí)候,在MyBatis的上下文初始化過程中,就開始讀入插件節(jié)點(diǎn)和我們配置的參數(shù),同時(shí)使用反射技術(shù)生成對(duì)應(yīng)的插件實(shí)例,然后調(diào)用插件方法中的setProperties方法,設(shè)置我們配置的參數(shù),然后將插件實(shí)例保存到配置對(duì)象中,以便讀取和使用它。

插件在Configuration對(duì)象中的保存:

  public void addInterceptor(Interceptor interceptor) {
    interceptorChain.addInterceptor(interceptor);
  }
3、插件的代理和反射設(shè)計(jì)

插件用的是責(zé)任鏈模式,MyBatis的責(zé)任鏈?zhǔn)怯蒳nterceptorChain去定義的。在MyBatis創(chuàng)建Executor執(zhí)行器的時(shí)候,我們可以看到有如下的一段代碼:

executor = (Executor) interceptorChain.pluginAll(executor);

再看下Interceptor的pluginAll方法:

public class InterceptorChain {
  private final List interceptors = new ArrayList();

  public Object pluginAll(Object target) {
    for (Interceptor interceptor : interceptors) {
      // plugin方法是生成代理對(duì)象的方法
      // 可以看出來,如果有多個(gè)插件的話,會(huì)生成多層代理的代理對(duì)象
      target = interceptor.plugin(target);
    }
    return target;
  }
  ......
}

MyBatis為我們提供了Plugin類用于生成代理對(duì)象。

public class Plugin implements InvocationHandler {
  ......

  public static Object wrap(Object target, Interceptor interceptor) {
    Map, Set> signatureMap = getSignatureMap(interceptor);
    Class type = target.getClass();
    Class[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
      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 methods = signatureMap.get(method.getDeclaringClass());
      // 如果存在簽名的攔截方法,插件的intercept方法將被調(diào)用
      if (methods != null && methods.contains(method)) {
        return interceptor.intercept(new Invocation(target, method, args));
      }
      // 否則,直接反射調(diào)度我們要執(zhí)行的方法
      return method.invoke(target, args);
    } catch (Exception e) {
      throw ExceptionUtil.unwrapThrowable(e);
    }
  }
}

在調(diào)用插件的攔截方法時(shí),可以看到傳遞了一個(gè)新創(chuàng)建的Invocation對(duì)象。

interceptor.intercept(new Invocation(target, method, args));

Invocation類封裝了被代理的對(duì)象、方法及其參數(shù)。

public class Invocation {
  public Invocation(Object target, Method method, Object[] args) {
    this.target = target;
    this.method = method;
    this.args = args;
  }

  // 這個(gè)方法會(huì)調(diào)度被代理對(duì)象的真實(shí)方法, 所以我們通過這個(gè)方法直接調(diào)用被代理對(duì)象原來的方法
  // 如果多個(gè)插件的話,我們知道會(huì)生成多層代理對(duì)象,那么每層被代理都可以通過Invocation調(diào)用這個(gè)proceed方法,
  // 所以在多個(gè)插件的環(huán)境下,調(diào)度proceed()方法時(shí),MyBatis總是從最后一個(gè)代理對(duì)象運(yùn)行到第一個(gè)代理對(duì)象,
  // 最后是真實(shí)被攔截的對(duì)象方法被運(yùn)行
  public Object proceed() throws InvocationTargetException, IllegalAccessException {
    return method.invoke(target, args);
  }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69549.html

相關(guān)文章

  • 深入淺出MyBatis筆記MyBatis的解析和運(yùn)行原理

    摘要:的解析和運(yùn)行原理構(gòu)建過程提供創(chuàng)建的核心接口。在構(gòu)造器初始化時(shí)會(huì)根據(jù)和的方法解析為命令。數(shù)據(jù)庫(kù)會(huì)話器定義了一個(gè)對(duì)象的適配器,它是一個(gè)接口對(duì)象,構(gòu)造器根據(jù)配置來適配對(duì)應(yīng)的對(duì)象。它的作用是給實(shí)現(xiàn)類對(duì)象的使用提供一個(gè)統(tǒng)一簡(jiǎn)易的使用適配器。 MyBatis的解析和運(yùn)行原理 構(gòu)建SqlSessionFactory過程 SqlSessionFactory提供創(chuàng)建MyBatis的核心接口SqlSess...

    bitkylin 評(píng)論0 收藏0
  • Mybatis學(xué)習(xí)筆記

    摘要:學(xué)習(xí)筆記有官方的中文開發(fā)文檔并且針對(duì)使用者比較友好是一款優(yōu)秀的持久層框架,它支持定制化存儲(chǔ)過程以及高級(jí)映射。它只和配置有關(guān),存在的意義僅在于用來減少類完全限定名的冗余,為了簡(jiǎn)化中的書寫。 Mybatis學(xué)習(xí)筆記 mybatis有官方的中文開發(fā)文檔并且針對(duì)使用者比較友好:http://www.mybatis.org/mybatis-3/zh/ MyBatis 是一款優(yōu)秀的持久層框架,它支...

    jsyzchen 評(píng)論0 收藏0
  • Java深入-框架技巧

    摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進(jìn)階面試問題列表 -...

    chengtao1633 評(píng)論0 收藏0
  • Java 實(shí)戰(zhàn)開發(fā)之mybatis三劍客(五)

    摘要:插件功能非常強(qiáng)大,,方法跳轉(zhuǎn)提示,分頁插件。三地址使用該插件在引入該插件具體使用,我們?cè)谝院蟮闹性賹W(xué)習(xí)具體的方法。更多請(qǐng)參考學(xué)習(xí)筆記一入門 mybatis 插件功能非常強(qiáng)大,mybatis-generator,mybatis-plugin方法跳轉(zhuǎn)提示,mybatis-pagehelper分頁插件。 一、mybatis-generator 1、mybatis-generator配置 先在...

    NusterCache 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<