亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > 幫助中心 > 正文

簡單了解mybatis攔截器實現原理及實例

2024-07-09 22:43:04
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了簡單了解mybatis攔截器實現原理及實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

例行慣例,先看些基本概念:

1 攔截器的作用就是我們可以攔截某些方法的調用,在目標方法前后加上我們自己邏輯

2 Mybatis攔截器設計的一個初衷是為了供用戶在某些時候可以實現自己的邏輯而不必去動Mybatis固有的邏輯。

自定義攔截器

/** * mybatis 自定義攔截器 * 三步驟: * 1 實現 {@link Interceptor} 接口 * 2 添加攔截注解 {@link Intercepts} * 3 配置文件中添加攔截器 * * 1 實現 {@link Interceptor} 接口 *   具體作用可以看下面代碼每個方法的注釋 * 2 添加攔截注解 {@link Intercepts} *   mybatis 攔截器默認可攔截的類型只有四種,即四種接口類型 Executor、StatementHandler、ParameterHandler 和 ResultSetHandler *   對于我們的自定義攔截器必須使用 mybatis 提供的注解來指明我們要攔截的是四類中的哪一個類接口 *   具體規則如下: *     a:Intercepts 攔截器: 標識我的類是一個攔截器 *     b:Signature 署名: 則是指明我們的攔截器需要攔截哪一個接口的哪一個方法 *       type  對應四類接口中的某一個,比如是 Executor *       method 對應接口中的哪類方法,比如 Executor 的 update 方法 *       args  對應接口中的哪一個方法,比如 Executor 中 query 因為重載原因,方法有多個,args 就是指明參數類型,從而確定是哪一個方法 * 3 配置文件中添加攔截器 *   攔截器其實就是一個 plugin,在 mybatis 核心配置文件中我們需要配置我們的 plugin : *     <plugin interceptor="liu.york.mybatis.study.plugin.MyInterceptor"> *       <property name="username" value="LiuYork"/> *       <property name="password" value="123456"/> *     </plugin> * * 攔截器順序 * 1 不同攔截器順序: *   Executor -> ParameterHandler -> StatementHandler -> ResultSetHandler * * 2 對于同一個類型的攔截器的不同對象攔截順序: *   在 mybatis 核心配置文件根據配置的位置,攔截順序是 從上往下 */@Intercepts({    @Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}),    @Signature(method = "query", type = StatementHandler.class, args = {Statement.class, ResultHandler.class})})public class MyInterceptor implements Interceptor {  /**   * 這個方法很好理解   * 作用只有一個:我們不是攔截方法嗎,攔截之后我們要做什么事情呢?   *   這個方法里面就是我們要做的事情   *   * 解釋這個方法前,我們一定要理解方法參數 {@link Invocation} 是個什么鬼?   * 1 我們知道,mybatis攔截器默認只能攔截四種類型 Executor、StatementHandler、ParameterHandler 和 ResultSetHandler   * 2 不管是哪種代理,代理的目標對象就是我們要攔截對象,舉例說明:   *   比如我們要攔截 {@link Executor#update(MappedStatement ms, Object parameter)} 方法,   *   那么 Invocation 就是這個對象,Invocation 里面有三個參數 target method args   *     target 就是 Executor   *     method 就是 update   *     args  就是 MappedStatement ms, Object parameter   *   *  如果還是不能理解,我再舉一個需求案例:看下面方法代碼里面的需求   *   * 該方法在運行時調用   */  @Override  public Object intercept(Invocation invocation) throws Throwable {    /*     * 需求:我們需要對所有更新操作前打印查詢語句的 sql 日志     * 那我就可以讓我們的自定義攔截器 MyInterceptor 攔截 Executor 的 update 方法,在 update 執行前打印sql日志     * 比如我們攔截點是 Executor 的 update 方法 : int update(MappedStatement ms, Object parameter)     *     * 那當我們日志打印成功之后,我們是不是還需要調用這個query方法呢,如何如調用呢?     * 所以就出現了 Invocation 對象,它這個時候其實就是一個 Executor,而且 method 對應的就是 query 方法,我們     * 想要調用這個方法,只需要執行 invocation.proceed()     */    /* 因為我攔截的就是Executor,所以我可以強轉為 Executor,默認情況下,這個Executor 是個 SimpleExecutor */    Executor executor = (Executor)invocation.getTarget();    /*     * Executor 的 update 方法里面有一個參數 MappedStatement,它是包含了 sql 語句的,所以我獲取這個對象     * 以下是偽代碼,思路:     * 1 通過反射從 Executor 對象中獲取 MappedStatement 對象     * 2 從 MappedStatement 對象中獲取 SqlSource 對象     * 3 然后從 SqlSource 對象中獲取獲取 BoundSql 對象     * 4 最后通過 BoundSql#getSql 方法獲取 sql     */    MappedStatement mappedStatement = ReflectUtil.getMethodField(executor, MappedStatement.class);    SqlSource sqlSource = ReflectUtil.getField(mappedStatement, SqlSource.class);    BoundSql boundSql = sqlSource.getBoundSql(args);    String sql = boundSql.getSql();    logger.info(sql);    /*     * 現在日志已經打印,需要調用目標對象的方法完成 update 操作     * 我們直接調用 invocation.proceed() 方法     * 進入源碼其實就是一個常見的反射調用 method.invoke(target, args)     * target 對應 Executor對象     * method 對應 Executor的update方法     * args  對應 Executor的update方法的參數     */    return invocation.proceed();  }  /**   * 這個方法也很好理解   * 作用就只有一個:那就是Mybatis在創建攔截器代理時候會判斷一次,當前這個類 MyInterceptor 到底需不需要生成一個代理進行攔截,   * 如果需要攔截,就生成一個代理對象,這個代理就是一個 {@link Plugin},它實現了jdk的動態代理接口 {@link InvocationHandler},   * 如果不需要代理,則直接返回目標對象本身   *   * Mybatis為什么會判斷一次是否需要代理呢?   * 默認情況下,Mybatis只能攔截四種類型的接口:Executor、StatementHandler、ParameterHandler 和 ResultSetHandler   * 通過 {@link Intercepts} 和 {@link Signature} 兩個注解共同完成   * 試想一下,如果我們開發人員在自定義攔截器上沒有指明類型,或者隨便寫一個攔截點,比如Object,那Mybatis瘋了,難道所有對象都去攔截   * 所以Mybatis會做一次判斷,攔截點看看是不是這四個接口里面的方法,不是則不攔截,直接返回目標對象,如果是則需要生成一個代理   *   * 該方法在 mybatis 加載核心配置文件時被調用   */  @Override  public Object plugin(Object target) {    /*     * 看了這個方法注釋,就應該理解,這里的邏輯只有一個,就是讓mybatis判斷,要不要進行攔截,然后做出決定是否生成一個代理     *     * 下面代碼什么鬼,就這一句就搞定了?     * Mybatis判斷依據是利用反射,獲取這個攔截器 MyInterceptor 的注解 Intercepts和Signature,然后解析里面的值,     * 1 先是判斷要攔截的對象是四個類型中 Executor、StatementHandler、ParameterHandler、 ResultSetHandler 的哪一個     * 2 然后根據方法名稱和參數(因為有重載)判斷對哪一個方法進行攔截 Note:mybatis可以攔截這四個接口里面的任一一個方法     * 3 做出決定,是返回一個對象呢還是返回目標對象本身(目標對象本身就是四個接口的實現類,我們攔截的就是這四個類型)     *     * 好了,理解邏輯我們寫代碼吧~~~ What !!! 要使用反射,然后解析注解,然后根據參數類型,最后還要生成一個代理對象     * 我一個小白我怎么會這么高大上的代碼嘛,怎么辦?     *     * 那就是使用下面這句代碼吧 哈哈     * mybatis 早就考慮了這里的復雜度,所以提供這個靜態方法來實現上面的邏輯     */    return Plugin.wrap(target, this);  }  /**   * 這個方法最好理解,如果我們攔截器需要用到一些變量參數,而且這個參數是支持可配置的,   * 類似Spring中的@Value("${}")從application.properties文件獲取   * 這個時候我們就可以使用這個方法   *   * 如何使用?   * 只需要在 mybatis 配置文件中加入類似如下配置,然后 {@link Interceptor#setProperties(Properties)} 就可以獲取參數   *   <plugin interceptor="liu.york.mybatis.study.plugin.MyInterceptor">   *      <property name="username" value="LiuYork"/>   *      <property name="password" value="123456"/>   *   </plugin>   *   方法中獲取參數:properties.getProperty("username");   *   * 問題:為什么要存在這個方法呢,比如直接使用 @Value("${}") 獲取不就得了?   * 原因是 mybatis 框架本身就是一個可以獨立使用的框架,沒有像 Spring 這種做了很多依賴注入的功能   *   * 該方法在 mybatis 加載核心配置文件時被調用    */  @Override  public void setProperties(Properties properties) {    String username = properties.getProperty("username");    String password = properties.getProperty("password");    // TODO: 2019/2/28 業務邏輯處理...  }}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
66m—66摸成人免费视频| 欧美在线观看一区二区三区| 国产精品一区二区三区成人| 欧美日韩ab片| 精品中文字幕在线2019| 欧美精品久久一区二区| 亚洲精品视频网上网址在线观看| 奇米一区二区三区四区久久| 两个人的视频www国产精品| 色999日韩欧美国产| 欧美老肥婆性猛交视频| 亚洲色图激情小说| 久久精品免费电影| 亚洲综合在线中文字幕| 色综久久综合桃花网| 国产精品成人一区| 亚洲激情久久久| 国产精品久久久久福利| 91av免费观看91av精品在线| 粉嫩av一区二区三区免费野| 久久中文精品视频| 亚洲深夜福利在线| 国产精品色午夜在线观看| 亚洲iv一区二区三区| 91高清免费视频| 亚洲成人精品久久久| 色偷偷av亚洲男人的天堂| 97色在线观看| 在线亚洲男人天堂| 久久精品视频99| 欧美一区二区三区图| 国产精品欧美久久久| 国产婷婷成人久久av免费高清| 欧美一区二三区| 中文字幕亚洲欧美| 黑人狂躁日本妞一区二区三区| 川上优av一区二区线观看| 亚洲第一av网| 亚洲一区二区三区乱码aⅴ| 性色av香蕉一区二区| 成人乱人伦精品视频在线观看| 日韩有码在线观看| 国产日韩欧美日韩大片| 亚洲综合在线做性| 亚洲国产成人91精品| 91av在线播放| 国产精品久久久久aaaa九色| 欧美精品videossex性护士| 亚洲国产精品成人va在线观看| 岛国av在线不卡| 欧美亚洲在线视频| 中文字幕一区二区精品| 国产亚洲欧洲高清一区| 91精品久久久久久久久久久久久| 最近2019好看的中文字幕免费| 国产视频久久网| 亚洲国产另类 国产精品国产免费| 国产精品久久久久久五月尺| 日韩精品中文字| 日本精品在线视频| 亚洲第一在线视频| 免费不卡在线观看av| 精品国产自在精品国产浪潮| 欧美国产日韩免费| 久久亚洲精品成人| 久久久99久久精品女同性| 中文一区二区视频| 国产偷亚洲偷欧美偷精品| 欧美午夜激情视频| 亚洲xxxxx电影| 亚洲精品国产精品乱码不99按摩| 亚洲专区在线视频| 丝袜亚洲欧美日韩综合| 欧美日韩国产一区二区三区| 午夜剧场成人观在线视频免费观看| 中文字幕亚洲一区二区三区| 91精品国产91久久久久久吃药| 日韩视频永久免费观看| 丰满岳妇乱一区二区三区| 91高清在线免费观看| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产精品人成电影| 亚洲欧洲日产国码av系列天堂| 亚洲人成欧美中文字幕| 中文字幕欧美日韩精品| 欧美孕妇与黑人孕交| 欧美国产在线电影| 动漫精品一区二区| 91色视频在线观看| 日韩av网址在线| 国产精品久久久久高潮| 91成人免费观看网站| 日韩人在线观看| 亚洲国产精久久久久久| 国产精品久久久久久久久男| 欧美大成色www永久网站婷| 亚洲va电影大全| 中文字幕av一区二区| 久久久精品美女| 亚洲人成网站777色婷婷| 亚洲第一网中文字幕| 日韩免费在线视频| 欧美成人午夜激情| 国产成人91久久精品| 欧美视频裸体精品| 亚洲黄色在线看| 国产精品永久免费观看| 久久手机精品视频| 国产成一区二区| 国产日韩在线一区| www.欧美免费| 5566日本婷婷色中文字幕97| 久久久综合av| 国产亚洲精品综合一区91| 亚洲综合中文字幕在线| 欧美性xxxxxxx| 亚洲自拍中文字幕| 国模视频一区二区三区| 欧美剧在线观看| 欧美激情欧美激情在线五月| 一夜七次郎国产精品亚洲| 亚洲国产另类久久精品| 欧美性极品xxxx做受| 三级精品视频久久久久| 国产在线观看一区二区三区| 欧美老肥婆性猛交视频| 日韩av在线看| 91精品国产91久久久久久吃药| 亚洲综合在线中文字幕| 97精品国产aⅴ7777| 欧美性受xxxx黑人猛交| 国产精品一区二区三区在线播放| 久久精品福利视频| 亚洲成色777777在线观看影院| 欧美日韩在线第一页| 岛国av午夜精品| 91久久精品一区| 国产日韩欧美视频在线| 精品一区电影国产| 成人黄色av免费在线观看| 日韩av成人在线| 久久亚洲私人国产精品va| 欧美极品少妇全裸体| 亚洲色图13p| 91精品视频免费观看| 国产精品久久久久久一区二区| 午夜精品福利电影| 亚洲少妇激情视频| 久久久久久亚洲精品中文字幕| 欧美日韩综合视频| 在线电影中文日韩| 欧洲成人在线观看| 国产精品女人久久久久久| 亚洲美女av网站| 欧美性极品xxxx做受| 亚洲天天在线日亚洲洲精| 91美女片黄在线观看游戏| 成人国产精品久久久久久亚洲| 全亚洲最色的网站在线观看| 一区二区三区日韩在线| 国产精品欧美日韩久久| 亚洲欧美精品在线| 久久影视电视剧免费网站| 91中文字幕在线观看|