全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📝 1 篇文章 10 道配套习题

插件开发高级应用专题

专题说明

本专题系统讲解MyBatis插件机制的核心原理与高级应用,涵盖JDK动态代理构建的代理链机制、多插件执行顺序、分页插件深度定制、数据脱敏插件、SQL审计日志插件等完整实战场景。

学习目标

  1. 理解MyBatis插件的JDK动态代理机制与代理链构建原理
  2. 掌握多插件执行顺序与invocation.proceed()的短路机制
  3. 学会开发支持多数据库方言的分页插件
  4. 掌握数据脱敏插件在ResultSetHandler和TypeHandler层面的实现
  5. 理解SQL审计日志插件的异步写入与敏感信息处理

学习内容

  • 插件代理链原理:Plugin.wrap()、JDK动态代理、责任链模式
  • 多插件执行顺序:XML配置顺序与intercept调用顺序的关系
  • 分页插件深度定制:Executor拦截、SQL改写、多数据库方言
  • 数据脱敏插件:@Sensitive注解、ResultSetHandler拦截、TypeHandler实现
  • SQL审计日志插件:异步写入、敏感信息脱敏、批量写入

学习建议

MyBatis插件机制是框架的核心扩展点,建议结合源码理解Plugin.wrap()的代理链构建过程。分页插件是实战中最常见的自定义插件类型,数据脱敏和审计日志插件是生产环境的典型需求。

📝 发现内容有误?点击此处直接编辑

📝 配套习题(10 题)

1
单选题

在 MyBatis 插件开发中,关于插件代理链(Plugin Chain)的执行机制,以下说法正确的是?

A

多个插件按照配置的顺序依次执行,每个插件独立拦截目标方法

B

多个插件会形成责任链,后一个插件的 invocation.proceed() 会调用下一个插件的 intercept 方法

C

插件代理链中,所有插件的 intercept 方法会被同时并发调用

D

插件代理链只能拦截 Executor 接口,无法拦截 StatementHandler 等其他接口

2
判断题

在 MyBatis 插件的 Plugin.wrap() 方法中,如果被代理对象已经是代理对象(即已经被前面的插件包装过),则不会再次创建新的代理,而是直接返回原有代理对象。()

A

B

3
多选题

在 MyBatis 配置文件 mybatis-config.xml 中按顺序配置了三个插件:

XML
<plugins>
    <plugin interceptor="com.example.PluginA"/>
    <plugin interceptor="com.example.PluginB"/>
    <plugin interceptor="com.example.PluginC"/>
</plugins>

关于这三个插件的执行顺序,以下说法正确的有哪些?

A

拦截 Executor.query 方法时,intercept 方法的调用顺序是 PluginA -> PluginB -> PluginC

B

拦截 Executor.query 方法时,intercept 方法的调用顺序是 PluginC -> PluginB -> PluginA

C

如果在 PluginB 的 intercept 方法中不调用 invocation.proceed(),则 PluginC 不会被执行

D

三个插件的 intercept 方法会按照 XML 配置顺序同时并发执行

4
填空题

假设 MyBatis 配置了两个插件:PluginX 和 PluginY(按此顺序配置)。当调用被代理的 Executor.query() 方法时,完整的调用链路为:

外部调用 query() -> !!1!!.intercept(invocation) -> invocation.proceed() -> !!2!!.intercept(invocation) -> invocation.proceed() -> 真实的 Executor.query()

请填写空白处的插件名称。

5
单选题

在开发 MyBatis 自定义分页插件时,以下哪种方案是实现分页功能最合理的做法?

A

拦截 ResultSetHandler.handleResultSets() 方法,在结果集返回后截取指定范围的数据

B

拦截 Executor.query() 方法,改写 SQL 添加 LIMIT 子句,并同时执行 COUNT 查询获取总数

C

在 Mapper 接口方法中手动拼接 LIMIT 子句,不使用插件机制

D

拦截 StatementHandler.prepare() 方法,修改 Connection 的 autoCommit 属性来实现分页

6
简答题

请设计一个支持多数据库方言(MySQL、Oracle、PostgreSQL)的分页插件的核心逻辑。要求:

  1. 说明拦截哪个接口的方法
  2. 如何处理不同数据库的分页 SQL 语法差异
  3. 如何同时获取总记录数
  4. 如何保证分页参数的正确传递
7
多选题

在设计 MyBatis 数据脱敏插件时,以下哪些场景适合通过插件实现敏感数据的自动脱敏处理?

A

拦截 ResultSetHandler.handleResultSets(),在结果映射后对包含 @Sensitive 注解的字段进行脱敏

B

拦截 ParameterHandler.setParameters(),对传入的查询参数中的敏感信息进行加密

C

拦截 Executor.update(),对 INSERT/UPDATE 语句中的敏感字段值进行自动加密存储

D

在 TypeHandler 层面实现字符串类型的统一脱敏转换

8
填空题

实现手机号脱敏工具方法,规则为:保留前 3 位和后 4 位,中间用 4 个 * 替换。例如 13812345678 脱敏后为 138****5678。

请补全以下代码:

Java
public static String maskPhone(String phone) {
    if (phone == null || phone.length() != !!1!!) {
        return phone;
    }
    return phone.substring(0, 3) + "!!2!!" + phone.substring(phone.length() - !!3!!);
}
9
多选题

开发 MyBatis SQL 审计日志插件时,以下哪些做法是正确的?

A

使用异步方式写入审计日志,避免阻塞正常业务 SQL 的执行

B

在拦截 Executor.update() 时,记录完整的 SQL 语句、参数值、执行耗时和操作人信息

C

使用 ThreadLocal 在请求入口处设置操作人信息,在插件中读取并写入审计日志

D

将审计日志直接 INSERT 到与业务相同的数据库中,共用同一个事务

10
简答题

请设计一个生产级别的 SQL 审计日志插件,要求回答以下问题:

  1. 应该拦截哪些 MyBatis 接口和方法?为什么?
  2. 如何在记录 SQL 参数的同时避免日志中打印敏感信息(如密码明文)?
  3. 审计日志的数据结构应包含哪些核心字段?
  4. 在高并发场景下,如何保证审计日志的写入性能?
← 上一个专题 接口绑定与动态代理专题
下一个专题 → 插件机制专题

📝 发现内容有误?点击此处直接编辑

想查看更多习题和详细解析?
小程序提供完整的题库和详细解析

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库