精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

MyBatis 的 SQL 攔截器:原理、實現與實踐

數據庫 其他數據庫
MyBatis的SQL?攔截器是其插件機制的核心,通過動態代理實現對SQL?執行過程的靈活干預。本文從原理(四大接口、動態代理)、實現(定義攔截器、聲明目標、配置生效)到實踐(日志統計、SQL修改、參數加密),全面解析了攔截器的使用。

前言

在MyBatis框架的使用過程中,我們常常需要對SQL執行過程進行干預 —— 比如打印執行日志、統計執行時間、動態修改SQL語句,甚至實現數據權限控制。而MyBatis提供的SQL攔截器(Interceptor)機制,正是實現這些需求的核心工具。

核心原理

MyBatis的SQL攔截器本質上是基于JDK動態代理實現的插件機制,它允許開發者在 SQL 執行的關鍵節點插入自定義邏輯。要理解其原理,需先明確兩個核心概念:攔截目標與代理機制。

核心接口
  • Executor:MyBatis的核心執行器,負責SQL的整體執行(如select、update、commit等),是最常用的攔截目標。
  • StatementHandler:處理SQL語句的準備(如創建 Statement)、參數設置、結果集映射等,可用于修改SQL語句或參數。
  • ParameterHandler:處理SQL參數的設置(如為PreparedStatement設置參數),適合攔截參數并進行加工。
  • ResultSetHandler:處理查詢結果集的映射(如將結果映射為Java對象),可用于修改返回結果。
代理機制

MyBatis的攔截器通過動態代理 + 責任鏈模式工作:當定義一個攔截器后,MyBatis會為被攔截的接口生成代理對象,將攔截邏輯嵌入代理對象中;若存在多個攔截器,則會形成代理鏈(外層代理調用內層代理,最終調用原始對象)。 具體流程如下:

  • 攔截器通過@Intercepts注解聲明攔截目標(接口、方法、參數);
  • MyBatise 啟動時掃描攔截器,為目標接口創建代理對象;
  • 當調用目標接口的方法時,代理對象先執行攔截器的intercept方法(自定義邏輯),再調用原始方法;
  • 若有多個攔截器,代理對象會按順序執行所有攔截邏輯后,再執行原始方法。

實現步驟

實現一個MyBatis SQL攔截器需遵循固定流程:定義攔截器類、聲明攔截目標、實現攔截邏輯,最后配置生效。下面以SQL 執行時間統計為例,詳解具體實現。

定義攔截器類:實現 Interceptor 接口

該接口包含3個核心方法:

  • intercept(Invocation invocation):核心方法,攔截邏輯的實現(如統計時間、修改參數)。
  • plugin(Object target):決定是否為目標對象生成代理(通常通過Plugin.wrap(target, this)實現)。
  • setProperties(Properties properties):接收配置文件中傳入的參數(如攔截器開關、日志級別)。
// 聲明攔截目標:攔截Executor的query和update方法
@Intercepts({
    @Signature(
        type = Executor.class, // 攔截的接口
        method = "query", // 攔截的方法
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} // 方法參數(需與接口方法一致)
    ),
    @Signature(
        type = Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class}
    )
})
public class SqlExecuteTimeInterceptor implements Interceptor {

    // 攔截邏輯:統計SQL執行時間
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 1. 記錄開始時間
        long startTime = System.currentTimeMillis();
        try {
            // 2. 執行原始方法(如query/update)
            return invocation.proceed();
        } finally {
            // 3. 計算執行時間并打印
            long endTime = System.currentTimeMillis();
            long cost = endTime - startTime;
            // 獲取SQL語句(從MappedStatement中提?。?            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
            String sqlId = mappedStatement.getId(); // Mapper接口方法全路徑
            System.out.printf("SQL執行:%s,耗時:%d ms%n", sqlId, cost);
        }
    }

    // 生成代理對象(固定寫法)
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    // 接收配置參數(如無需參數可空實現)
    @Override
    public void setProperties(Properties properties) {
        // 例如:從配置中獲取閾值,超過閾值打印警告
        String threshold = properties.getProperty("slowSqlThreshold");
        if (threshold != null) {
            // 處理參數...
        }
    }
}

聲明攔截目標:@Intercepts 與 @Signature

攔截器必須通過@Intercepts和@Signature注解明確攔截目標,否則MyBatis無法識別攔截邏輯。

  • @Intercepts:包裹一個或多個@Signature,表示攔截的一組目標。
  • @Signature:定義單個攔截目標,包含3個屬性:

type:被攔截的接口(如Executor、StatementHandler);

method:被攔截的方法名(如Executor的query、update);

args:被攔截方法的參數類型數組(需與接口方法參數完全一致,用于區分重載方法)。

配置攔截器:讓 MyBatis 識別攔截器

方式 1:MyBatis 原生配置(mybatis-config.xml)
<configuration>
  <plugins>
    <!-- 配置SQL執行時間攔截器 -->
    <plugin interceptor="com.example.SqlExecuteTimeInterceptor">
      <!-- 可選:傳入參數(對應setProperties方法) -->
      <property name="slowSqlThreshold" value="500"/> <!-- 慢SQL閾值:500ms -->
    </plugin>
  </plugins>
</configuration>
方式 2:Spring Boot 配置(通過 @Bean 注冊)
@Configuration
public class MyBatisConfig {
    @Bean
    public SqlExecuteTimeInterceptor sqlExecuteTimeInterceptor() {
        SqlExecuteTimeInterceptor interceptor = new SqlExecuteTimeInterceptor();
        // 設置參數
        Properties properties = new Properties();
        properties.setProperty("slowSqlThreshold", "500");
        interceptor.setProperties(properties);
        return interceptor;
    }
}

實戰案例

動態修改 SQL(如數據權限控制)

對多租戶系統,自動在SQL中添加租戶ID條件(如where tenant_id = 123),避免手動編寫。

@Override
public Object intercept(Invocation invocation) throws Throwable {
    // 獲取StatementHandler及原始SQL
    StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
    String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
    // 獲取當前租戶ID(從ThreadLocal或登錄上下文獲?。?    String tenantId = TenantContext.getCurrentTenantId(); // 自定義上下文類

    // 拼接租戶條件(簡單示例:僅對SELECT語句處理)
    if (originalSql.trim().toLowerCase().startsWith("select") && tenantId != null) {
        String modifiedSql = originalSql + " and tenant_id = " + tenantId;
        // 修改SQL
        metaObject.setValue("delegate.boundSql.sql", modifiedSql);
    }

    return invocation.proceed(); // 執行修改后的SQL
}
參數加密與解密

對敏感參數(如手機號、身份證號)在入庫前加密,查詢時解密。

@Override
public Object intercept(Invocation invocation) throws Throwable {
    ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
    MetaObject metaObject = SystemMetaObject.forObject(parameterHandler);
    // 獲取參數對象(如User對象)
    Object parameter = metaObject.getValue("parameterObject");
    if (parameter instanceof User) {
        User user = (User) parameter;
        // 加密手機號
        if (user.getPhone() != null) {
            user.setPhone(EncryptUtil.encrypt(user.getPhone())); // 自定義加密工具
        }
    }
    return invocation.proceed(); // 執行參數設置
}

注意事項

避免過度攔截,控制攔截范圍

攔截器會嵌入SQL執行流程,過多或過頻繁的攔截會增加性能開銷(尤其是query、prepare等高頻方法)。建議:

  • 僅攔截必要的接口和方法(如統計時間用Executor,改SQL用StatementHandler);
  • 避免在攔截邏輯中執行耗時操作(如IO、復雜計算)。

處理代理對象:獲取原始對象

由于MyBatis會對目標接口生成代理,直接調用invocation.getTarget()可能得到代理對象(而非原始對象),需通過反射或MetaObject獲取原始對象(如StatementHandler的delegate屬性)。

推薦使用MyBatis提供的SystemMetaObject工具類處理反射,避免手動編寫反射代碼:

MetaObject metaObject = SystemMetaObject.forObject(target);
// 獲取原始StatementHandler(delegate為StatementHandler代理的原始對象)
Object originalHandler = metaObject.getValue("delegate");

控制攔截器順序:@Order 或配置順序

若存在多個攔截器,執行順序由注冊順序決定(先注冊的先執行)。在Spring環境中,可通過@Order注解指定順序(值越小越先執行):

@Order(1) // 第一個執行
public class SqlLogInterceptor implements Interceptor { ... }

@Order(2) // 第二個執行
public class SqlModifyInterceptor implements Interceptor { ... }

總結

MyBatis的SQL攔截器是其插件機制的核心,通過動態代理實現對SQL執行過程的靈活干預。本文從原理(四大接口、動態代理)、實現(定義攔截器、聲明目標、配置生效)到實踐(日志統計、SQL修改、參數加密),全面解析了攔截器的使用。

合理使用攔截器可以簡化代碼(如自動添加租戶條件)、增強可觀測性(如SQL日志),但需注意性能與兼容性。

責任編輯:武曉燕 來源: 一安未來
相關推薦

2025-07-15 02:00:00

2009-06-04 08:01:25

Struts2攔截器原理

2025-01-02 10:10:51

2025-08-07 07:36:06

2024-02-28 09:35:52

2023-03-10 19:36:47

2024-05-06 00:00:00

C#工具代碼

2023-09-05 08:58:07

2011-05-16 10:14:11

Hibernate

2011-11-21 14:21:26

SpringMVCJava框架

2009-07-08 17:02:11

JDK實現調用攔截器

2024-12-27 08:39:10

2025-07-30 01:00:25

2009-06-25 15:59:21

Struts2教程攔截器

2012-02-03 13:27:16

2025-05-09 08:20:50

2009-06-24 16:00:00

2009-02-04 14:45:06

2009-09-27 17:37:32

Hibernate攔截

2025-02-28 08:14:53

點贊
收藏

51CTO技術棧公眾號

色婷婷av一区二区三区软件| 日韩久久久久久久久久久久| 天天干天天操天天爱| 亚洲在线成人| 亚洲精品按摩视频| the porn av| 欧美黑人猛交的在线视频| 97精品久久久午夜一区二区三区| 国产玖玖精品视频| 日本午夜小视频| 色一区二区三区四区| 亚洲成人av中文字幕| 50路60路老熟妇啪啪| 亚洲七七久久综合桃花剧情介绍| 久久天天做天天爱综合色| 92看片淫黄大片看国产片| 青青青国产在线| 国内精品福利| 久久精品国产一区二区电影| mm131丰满少妇人体欣赏图| 欧美国产亚洲精品| 欧美午夜在线观看| 2022亚洲天堂| 污污的视频在线观看| 国产精品网站在线播放| 美国av一区二区三区| 丰满熟妇乱又伦| 激情五月婷婷综合网| 国产成人一区二区三区电影| 日韩欧美a级片| 欧美在线日韩| 久久久精品一区| 成人18视频免费69| 欧美日韩一区二区三区视频播放| 日韩www在线| 国产精品一区二区在线免费观看| 国产精品视频一区二区三区综合| 欧美调教femdomvk| 黄色一级二级三级| 欧美电影h版| 精品欧美一区二区三区| 欧洲精品一区二区三区久久| 91小视频xxxx网站在线| 亚洲欧美乱综合| 中文精品视频一区二区在线观看| av电影在线观看| 久久精品无码一区二区三区| 欧美一区二区三区四区夜夜大片| 日本大片在线观看| 91麻豆国产福利在线观看| 久久免费一区| 精品视频一二区| 久久久青草青青国产亚洲免观| 精品国产综合| 深夜影院在线观看| 97se亚洲国产综合自在线不卡 | 国产精品2024| 亚洲在线第一页| 性一交一乱一伧老太| 成人一区二区在线观看| 国产欧美日韩一区| 人成在线免费视频| 日本一区二区不卡视频| 亚洲最大免费| 中文在线免费| 99视频国产精品免费观看a| 九色综合国产一区二区三区| 国产乱肥老妇国产一区二| 国产精品爱久久久久久久| 五月天亚洲视频| 欧美黄页在线免费观看| 777久久久精品| 台湾佬美性中文| 欧美一级色片| 国产亚洲精品va在线观看| 亚洲激情图片网| 欧美激情亚洲| 欧美性视频精品| 国产精品国产精品国产| 加勒比av一区二区| 国产伦精品一区二区三区视频孕妇 | 国产高清视频在线观看| 中文字幕亚洲精品在线观看| 日本a在线天堂| 伊人网在线播放| 欧美日韩国产大片| 青青草视频网站| 欧美在线电影| 欧美精品18videosex性欧美| 中文人妻av久久人妻18| 精品一区二区久久久| 国产精品久久久久久久小唯西川| 国产精品一二三区视频| 亚洲乱码精品一二三四区日韩在线| 欧美成人高潮一二区在线看| 国产私拍福利精品视频二区| 精品国精品国产| 国产传媒视频在线| 亚洲欧洲一区二区天堂久久| 国产精品毛片a∨一区二区三区|国 | 三上悠亚国产精品一区二区三区| 91精品欧美综合在线观看最新| 日本黄色免费观看| 999久久久精品国产| 综合久久一区| 九九热视频这里只有精品| 少妇太紧太爽又黄又硬又爽| 国产乱对白刺激视频不卡| 欧美精品人人做人人爱视频| 性欧美video高清bbw| 日本高清无吗v一区| 久久久久亚洲av无码网站| 日韩精品2区| 91精品国产色综合久久不卡98口| 91丨porny丨在线中文 | 亚洲精品视频在线| 97视频久久久| 自拍偷拍欧美日韩| 亚洲视频国产视频| 欧美成人手机视频| 日韩中文字幕1| 精品一区久久久久久| 最新av在线播放| 欧美少妇bbb| 一级黄色片大全| 激情综合自拍| 99r国产精品视频| 国产三区在线观看| 欧美日韩在线免费视频| 久久久久亚洲av无码专区桃色| 欧美日韩影院| 18成人在线| 欧美a免费在线| 欧美视频中文一区二区三区在线观看| 中国极品少妇videossexhd| 欧美成人午夜| 亚洲一区二区中文| 亚洲按摩av| 日韩午夜在线播放| 青草草在线视频| 国产精品自拍av| 九九久久九九久久| 日韩精品一区二区三区中文字幕| 久久精品国产一区二区三区| 一级久久久久久久| 亚洲欧美自拍偷拍| 超碰在线资源站| 欧美国产高清| 国产91色在线|亚洲| 久久av色综合| 欧美大胆一级视频| 黄色小说在线观看视频| 国产成人精品免费看| 日韩一级特黄毛片| 超碰精品在线| 欧美影院在线播放| 成人18在线| 欧美精品丝袜中出| 精品无码久久久久成人漫画| 成人高潮片免费视频| 国产精品欧美综合在线| 激情五月婷婷久久| 97在线精品| 99超碰麻豆| 亚洲国产精品va在线观看黑人| 亚洲熟妇无码另类久久久| 51亚洲精品| 91精品国产91久久久久福利| 亚洲日本中文字幕在线| 色综合久久久久综合体桃花网| 美女100%无挡| 国产在线视频精品一区| 日韩黄色片在线| 午夜a一级毛片亚洲欧洲| 国产精品福利在线观看网址| 毛片av在线| 欧美精品一区男女天堂| 精品国产xxx| 亚洲欧美另类小说| 亚洲黄色免费在线观看| 蜜臀久久99精品久久久久宅男 | 污污内射在线观看一区二区少妇 | 一级黄色大片免费看| 亚洲三级观看| 亚洲一区二区不卡视频| 丁香婷婷成人| 国产精品露脸自拍| 91超碰在线| 中文字幕综合一区| 欧美 日韩 中文字幕| 色噜噜狠狠成人网p站| 精品国产乱码久久久久久鸭王1| 97精品国产97久久久久久久久久久久| 国产一区二区在线免费播放| 激情久久久久| 亚洲一区三区| 亚洲人成网77777色在线播放 | 91成人在线免费| 欧美日韩久久久久| 日韩一区二区不卡视频| 久久综合网色—综合色88| 91香蕉国产线在线观看| 视频在线观看一区| 69精品丰满人妻无码视频a片| 国产毛片一区二区三区| 超碰97人人人人人蜜桃| 俄罗斯黄色录像| 青娱乐精品在线视频| 欧美大黑帍在线播放| 成人亚洲一区二区| 国产精品一区二区三区四区五区| 欧美mv日韩mv| 永久免费未满蜜桃| 日韩高清电影一区| 欧美日韩激情四射| 日韩在线观看| 欧美重口乱码一区二区| 福利在线一区| 91精品国产一区二区三区动漫| 欧美成a人片在线观看久| 久久久日本电影| 菠萝菠萝蜜在线视频免费观看| 亚洲片在线资源| 国产精品亚洲网站| av免费网站观看| 日韩.com| 欧美激情导航| 色爱综合av| 国内精品二区| 嫩草国产精品入口| 国产在线播放一区二区| 91网站在线观看免费| 成人av婷婷| 成人在线视频网址| 成人污污视频| 中文在线一区二区| 黄色片视频免费观看| 粉嫩aⅴ一区二区三区四区| 亚洲图片 自拍偷拍| 久久aⅴ国产欧美74aaa| 欧美第一页浮力影院| 免费在线观看不卡| 一道本视频在线观看| 日韩专区一卡二卡| 久草青青在线观看| 欧美一级网站| 国产一级片黄色| 日韩精品五月天| 波多结衣在线观看| 美美哒免费高清在线观看视频一区二区| 亚洲狼人综合干| 欧美aⅴ一区二区三区视频| 国产视频在线视频| 日本成人在线一区| 深夜黄色小视频| 欧美黄色小视频| 青青草免费在线| 亚洲精品在线91| 九色网友自拍视频手机在线| 精品五月天久久| 国产区在线视频| 中文字幕视频一区二区在线有码 | 惠美惠精品网| 国产成人亚洲综合91精品| 国产91亚洲精品久久久| 成人国内精品久久久久一区| 国产高清精品二区| 国产精品一区二区欧美黑人喷潮水 | www.自拍偷拍| 亚洲国产精品成人综合| 啪啪一区二区三区| 亚洲自拍偷拍九九九| 欧美啪啪小视频| 欧美美女一区二区三区| 精品国产乱码一区二区三| 亚洲成人激情在线观看| 免费国产在线观看| 久久香蕉国产线看观看av| 欧美性爽视频| 国产va免费精品高清在线观看| 欧美日韩免费电影| 国产精品18毛片一区二区| 三区视频在线观看| 亚洲图片自拍偷拍| 公侵犯人妻一区二区三区| 久久精品一区二区三区不卡| 久久久精品成人| 亚洲欧美一区二区三区国产精品| 久久久久久av无码免费网站| 欧美日韩中文字幕综合视频 | 国产精品ⅴa有声小说| 日韩在线视频二区| 日韩欧美在线一区| 中国丰满熟妇xxxx性| 午夜一级久久| 五月天婷婷影视| 91污片在线观看| 精品一区在线观看视频| 色综合久久中文综合久久牛| 国产精品无码久久av| 亚洲精品乱码久久久久久金桔影视 | www.在线视频| 国产999精品| 99久久精品费精品国产一区二区| 一区二区三区四区五区视频| 在线观看国产精品入口| 国产精品视频一区二区三区四区五区| 麻豆精品在线播放| 成人免费av片| 亚洲综合在线观看视频| 亚洲一级黄色大片| 亚洲男人天堂古典| xxxx在线视频| 亚洲已满18点击进入在线看片| 少妇精品久久久一区二区| 人人妻人人做人人爽| 国产一区二区三区美女| 自拍偷拍你懂的| 日本久久一区二区三区| 色哟哟国产精品色哟哟| 欧美肥老妇视频| 亚洲精品aaa| 亚洲精品乱码视频| 天堂va蜜桃一区二区三区| 三叶草欧洲码在线| 午夜伊人狠狠久久| 亚洲精品综合网| 欧美丰满片xxx777| 91成人在线精品视频| 亚洲啊啊啊啊啊| 韩国毛片一区二区三区| 林心如三级全黄裸体| 欧美午夜理伦三级在线观看| 可以直接在线观看的av| 91av视频导航| 欧美一区二区三区红桃小说| 国产人妻777人伦精品hd| 国产传媒久久文化传媒| 欧美三级日本三级| 日韩一区二区视频| 50度灰在线| 亚洲在线视频观看| 欧美+亚洲+精品+三区| 精品国产一二区| 亚洲国产精品久久久男人的天堂| 亚洲国产精品久久久久爰性色| 色与欲影视天天看综合网| 日韩区一区二| 日韩欧美不卡在线| 91在线国产观看| 日本视频免费观看| 这里只有精品在线播放| 另类一区二区三区| 99亚洲精品视频| 国产精品原创巨作av| 免费一级片在线观看| 亚洲成人久久一区| 日本在线高清| 性欧美精品一区二区三区在线播放| 日本不卡视频在线观看| 久久精品亚洲a| 欧美大片顶级少妇| 男人天堂视频在线观看| 欧洲视频一区二区三区| 久久99精品久久只有精品| 欧美三级在线免费观看| 亚洲精品久久久久中文字幕欢迎你 | 精品亚洲免a| 激情六月丁香婷婷| 国产精品伦理在线| www.97av| 日本久久亚洲电影| 久久国产亚洲精品| 日韩女优在线视频| 在线视频一区二区免费| 99视频免费在线观看| 久久免费一区| 狠狠色狠狠色合久久伊人| 福利一区二区三区四区| 在线播放国产一区中文字幕剧情欧美| 自拍偷拍亚洲图片| 久久久一本二本三本| 中文字幕免费一区| 性欧美ⅴideo另类hd| 午夜视频一区二区三区| 青春草在线观看| 国产一区红桃视频| 激情偷拍久久| 亚洲女优在线观看| 日韩欧美国产电影| 欧美日韩五区| 亚洲一区二区三区av无码| 久久午夜国产精品| 国内老熟妇对白hdxxxx| 国产成人综合av| 亚洲午夜av| 男人晚上看的视频| 亚洲欧美国产视频| 一区二区亚洲视频| 免费看污黄网站|