精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

日本午夜精品久久久久| 水莓100国产免费av在线播放| 欧美xxxxx视频| 欧美日本不卡视频| 欧洲精品在线播放| 日本不卡视频一区二区| 日韩电影在线观看一区| 久久精品成人欧美大片| 男人添女人荫蒂国产| 亚洲天堂手机| 最好看的中文字幕久久| 精品日韩欧美| 国产美女永久免费| 亚洲女人av| 欧美成人激情视频免费观看| 中国美女乱淫免费看视频| 亚洲精品伦理| 精品久久久久久中文字幕一区奶水 | 国产一区二区播放| 欧美午夜18电影| 3d动漫精品啪啪| 久久久久免费精品| 爱搞国产精品| 亚洲欧美日韩中文播放| 日本一区二区三区视频在线播放 | 日韩久久精品成人| 国产xxx在线观看| 欧美啪啪网站| 在线中文字幕不卡| 北条麻妃在线视频观看| 黑人精品视频| 亚洲乱码一区二区三区在线观看| 日韩亚洲视频在线| 青青国产在线| 99国产精品国产精品久久| 91免费看网站| 国产欧美熟妇另类久久久 | 欧美在线亚洲在线| 久青草视频在线观看| 91精品秘密在线观看| 一区二区三区四区在线观看视频 | 中文无字幕一区二区三区| 国产精品区一区| 亚洲伦理在线观看| 国产精品一二三在| 成人中心免费视频| 91亚洲欧美激情| 久久激情五月婷婷| 成人国产精品一区| 97成人在线观看| 久久se精品一区精品二区| 国产精品精品视频| 国产精品熟女视频| 日韩av不卡在线观看| 国产精品成人v| 中文字幕人妻一区二区在线视频| 日韩精品国产精品| 国产精品成人免费电影| 国产精品欧美综合| 日韩高清一级片| 国产精品国内视频| 伊人网综合在线| 精品一区二区三区欧美| 91免费电影网站| 99re只有精品| 国产不卡高清在线观看视频| 高清国语自产拍免费一区二区三区| 国产ts人妖调教重口男| 国产高清亚洲一区| 国产精品乱码一区二区三区| 韩国av免费在线观看| av电影一区二区| 欧美日韩在线观看一区| 91精彩在线视频| 1024成人网| 欧美一区二区三区综合| 看黄在线观看| 精品视频1区2区3区| 国产欧美一区二| 88久久精品| 亚洲欧美日韩综合| 日本一级片免费| 国内自拍视频一区二区三区| 欧美在线观看网站| 亚洲视频中文字幕在线观看| 国产成人小视频| 欧美污视频久久久| 国产原创精品视频| 精品久久中文字幕| 91看片在线免费观看| 亚洲精品v亚洲精品v日韩精品| 亚洲激情国产精品| 国产99在线 | 亚洲| 欧美激情91| 欧美在线免费观看| 99精品在线看| 久久久久久久久蜜桃| 在线免费观看一区二区三区| gogo高清在线播放免费| 欧美午夜影院一区| 秘密基地免费观看完整版中文| 神马电影久久| 欧美激情一级欧美精品| 亚洲第一区av| 成人av高清在线| 一区二区在线不卡| 中文字幕在线中文字幕在线中三区| 欧美日韩精品欧美日韩精品一| 奇米777第四色| 88国产精品视频一区二区三区| 午夜精品福利在线观看| 国产精品-色哟哟| 久久久蜜桃精品| 久久福利一区二区| 日韩黄色在线| 亚洲女人初尝黑人巨大| 久久午夜无码鲁丝片午夜精品| 免费在线一区观看| 精品国产一区二区三区免费| 黄色在线论坛| 欧美优质美女网站| 成年人在线观看av| 极品av少妇一区二区| 91免费福利视频| 午夜视频成人| 色婷婷国产精品久久包臀| 人妻 丝袜美腿 中文字幕| 四虎成人精品永久免费av九九| 欧美在线激情视频| 天堂在线观看av| 亚洲一区二区三区在线播放| 毛片毛片毛片毛片毛| 国产精品不卡| 国产精品亚洲第一区| 欧美色图另类| 黑人精品xxx一区一二区| 潘金莲一级淫片aaaaaaa| 久久精品国产亚洲夜色av网站| 国产成人短视频| 欧美女子与性| 精品久久中文字幕| 91玉足脚交白嫩脚丫| 亚洲一级黄色| 亚洲av中文无码乱人伦在线视色| 亚洲精品小说| 91精品国产自产在线老师啪| 国产高清美女一级毛片久久| 一本色道a无线码一区v| 加勒比精品视频| 在线午夜精品| 久久99国产精品99久久| 九色porny自拍视频在线播放| 欧美videos大乳护士334| 麻豆成人在线视频| 国产成人亚洲综合a∨婷婷| 欧美一级中文字幕| 香港久久久电影| 欧美极品少妇与黑人| 亚洲毛片在线播放| 精品久久久久久亚洲国产300| 亚洲天堂成人av| 亚洲优女在线| 香蕉久久一区| 在线成人高清不卡| 国产黄在线免费观看| 国产福利91精品| 亚洲熟妇无码av在线播放| 综合视频一区| 91爱爱小视频k| 精品福利视频导航大全| 欧美色大人视频| 91n在线视频| 国产黄色91视频| 成人在线观看你懂的| 亚洲日产av中文字幕| 国产精品视频中文字幕91| 国产黄色在线免费观看| 精品88久久久久88久久久 | 亚洲一区在线观看免费 | 国产精品美女一区二区| 在线观看av免费观看| 亚洲性人人天天夜夜摸| 久久伊人资源站| 99久久久国产精品免费调教网站| 欧美成人三级视频网站| 开心激情综合网| 在线免费不卡电影| 欧美成人三级视频| www亚洲一区| 欧洲在线免费视频| 中日韩男男gay无套| 亚洲高清乱码| av综合网址| 国产精品美女免费| 日本欧美电影在线观看| 亚洲人a成www在线影院| 国产乱码精品一区二三区蜜臂 | 国产高清视频一区二区| 欧美亚洲日本网站| 国产素人视频在线观看| 国产视频精品久久久| 国产绿帽刺激高潮对白| 色综合久久久久综合体| 天堂网avav| 久久久久国产精品麻豆ai换脸 | 91在线观看污| 日本成人xxx| 免费中文字幕日韩欧美| 亚洲激情免费视频| 波多野结衣在线播放一区| 国产一区二区三区奇米久涩 | 精品一区国产| 国产日韩欧美中文在线| 国产精品aaaa| 1024在线看片你懂得| 久久精品最新地址| 国产一区二区影视| 日韩成人中文字幕在线观看| 国产wwwxxx| 欧美性受xxxx| 成人毛片在线播放| 午夜婷婷国产麻豆精品| www.毛片com| 成人免费在线观看入口| 亚洲不卡的av| 久久精品这里都是精品| 精品无码在线视频| 成人美女视频在线观看| 中文字幕乱妇无码av在线| 理论片日本一区| 欧美伦理片在线看| 久久久综合网| 日日鲁鲁鲁夜夜爽爽狠狠视频97 | 国产精品欧美精品| av网站免费在线看| 91麻豆免费观看| 国产亚洲色婷婷久久99精品91| 国产成人av电影在线| 久久综合在线观看| 精品亚洲porn| 在线观看免费污视频| 免费av成人在线| 波多野结衣xxxx| 蜜乳av一区二区三区| 天天干天天操天天玩| 麻豆成人久久精品二区三区小说| 在线视频日韩一区 | 久久aaaa片一区二区| 国产乱码字幕精品高清av| 久久精品一卡二卡| 国产一区二区三区在线观看精品 | 91免费观看视频在线| 亚洲最大的黄色网| ww亚洲ww在线观看国产| 免费在线观看污| 日本一区二区免费在线| 国产一二三av| av成人手机在线| 亚洲天堂免费看| 国产1区2区3区4区| 亚洲精品免费一二三区| 成人免费视频网站入口::| 亚洲品质自拍视频网站| 免费一级肉体全黄毛片| 亚洲成av人片| 国产精品va无码一区二区三区| 色综合久久综合网97色综合 | 国产黄a三级三级三级av在线看| 精品国产一区二区三区久久狼黑人 | 欧美交换国产一区内射| 亚洲一二三四久久| 国产精品suv一区二区69| 欧美日韩国产一中文字不卡 | 9191久久久久久久久久久| 国产深喉视频一区二区| 亚洲国产欧美日韩精品| 国产精品视频二区三区| 久久夜色精品国产| 大菠萝精品导航| 国产精品久久久久久久av大片| av日韩久久| 国产在线一区二区三区播放| 红桃成人av在线播放| 老汉色影院首页| 国产日韩欧美一区| 天堂av在线8| 99这里只有久久精品视频| 国产成人一区二区在线观看| 亚洲精品视频在线| 天堂网视频在线| 日韩一二三区视频| 精品视频一二区| 欧美日韩福利视频| 国产电影一区二区三区爱妃记| 亚洲va电影大全| 亚洲素人在线| 欧美三级午夜理伦三级老人| 蜜乳av另类精品一区二区| 亚洲第一成肉网| 国产清纯白嫩初高生在线观看91| 青青草手机视频在线观看| 91福利小视频| 色婷婷av一区二区三| 久久精品小视频| 免费h视频在线观看| 亚洲淫片在线视频| 精品国产一区二区三区| 男人的天堂avav| 另类欧美日韩国产在线| 日韩片在线观看| 亚洲男人的天堂一区二区| wwwwww在线观看| 国产视频在线一区二区| 色呦呦在线观看视频| 91精品久久久久久久久不口人| 亚洲人成网亚洲欧洲无码| 国产传媒久久久| 久久99国产精品久久99| 国产 欧美 在线| 精品国产户外野外| www.四虎在线观看| 日韩中文字幕不卡视频| 欧美aa视频| 久久国产精品99久久久久久丝袜 | 欧美日韩爱爱视频| 久久精品xxxxx| 日韩精品第一页| 久久久久久黄| 国产三级国产精品| 婷婷综合五月天| 国精品人妻无码一区二区三区喝尿| 久久天堂av综合合色| 欧美特黄色片| 视频一区视频二区视频| 首页综合国产亚洲丝袜| 国产肉体xxxx裸体784大胆| 亚洲成人自拍偷拍| 免费观看成年人视频| 欧美高清性猛交| 欧美专区视频| www.男人天堂网| 国产成人午夜99999| 综合五月激情网| 欧美一级生活片| 色yeye免费人成网站在线观看| 91视频免费进入| 午夜欧美精品| 无码人妻一区二区三区在线| 一区二区激情小说| 亚洲精品911| 午夜精品久久久久久久99热 | 国产精品亚洲人在线观看| 岛国毛片在线观看| 精品日韩在线观看| 福利在线导航136| 国产一区二区无遮挡| 国产日韩欧美高清免费| 一区二区三区四区免费| 欧美主播一区二区三区| 欧美精品videos另类| 亚洲一区二区久久久久久| 欧美日韩99| 538国产视频| 色94色欧美sute亚洲线路一ni | 欧美肥臀大乳一区二区免费视频| 99久久人爽人人添人人澡| 免费在线观看视频a| 久久久午夜精品| 在线免费观看日韩视频| 久热精品视频在线| 99这里只有精品视频| 欧美a v在线播放| 久久精品亚洲国产奇米99| 日本一区二区三区久久| 久久影院免费观看| 波多野结衣一区二区三区免费视频| 777777av| 欧美国产综合一区二区| 国产老妇伦国产熟女老妇视频| 欧美激情亚洲综合一区| 免费久久精品| 手机av在线网站| 婷婷久久综合九色综合绿巨人| 黄色片在线免费观看| 亚洲自拍另类欧美丝袜| 国产一区二区你懂的| 丁香六月激情综合| 亚洲аv电影天堂网| 欧美不卡高清一区二区三区| 欧美与动交zoz0z| 久久网站热最新地址| 91 中文字幕| 国语自产在线不卡| 久久影院100000精品| 久久久久久婷婷| 777色狠狠一区二区三区| 极品视频在线| 中文字幕av导航| 久久亚洲欧美国产精品乐播| a天堂中文在线观看|