当前位置: 首页 > news >正文

手写MyBatis第43弹:插件拦截原理与四大可拦截对象详解

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞

💖📕🎉🔥 支持我:点赞👍+收藏⭐️+留言📝欢迎留言讨论

🔥🔥🔥(源码 + 调试运行 + 问题答疑)

🔥🔥🔥  有兴趣可以联系我。

我们常常在当下感到时间慢,觉得未来遥远,但一旦回头看,时间已经悄然流逝。对于未来,尽管如此,也应该保持一种从容的态度,相信未来仍有许多可能性等待着我们。 

  1. 手写MyBatis阶段总结:从CRUD到架构优化,迈向插件开发新征程

  2. MyBatis框架设计深度解析:插件拦截原理与四大可拦截对象详解

  3. 从执行器优化到插件机制:手写MyBatis的架构演进与设计思想

  4. MyBatis插件开发完全指南:揭秘Interceptor链的实现原理与应用场景


在我们手写MyBatis的系列旅程中,我们已经成功搭建了一个具备完整CRUD功能的ORM框架雏形。从最初的配置解析、Mapper代理机制,到SQL执行器、参数处理、结果集映射,再到最近的返回值类型适配和Executor职责分离,我们的框架已经完成了从"能用"到"好用"的关键进化。此刻,让我们暂作停留,回顾已实现的核心功能,并前瞻性地探索MyBatis最强大的特性之一——插件机制。

一、阶段成果回顾:我们构建了什么?

我们的迷你MyBatis框架已经具备了现代ORM框架的核心骨架:

  1. 完整的CRUD操作:支持通过Mapper接口和SqlSession两种方式执行增删改查,其中增删改操作还能智能适配void、int、boolean等多种返回值类型。

  2. 清晰的核心组件协作:各个组件职责分明,形成了精密的协作体系:

  3. 优化的架构设计:通过最近的重构,我们实现了关键职责的分离:

    • 连接管理职责移交给了Transaction接口

    • Statement创建和执行职责移交给了StatementHandler hierarchy

    • Executor现在更加专注于执行流程的调度和控制

二、迈向高级特性:为什么需要插件机制?

尽管我们的框架已经功能完备,但在实际企业级应用中,我们经常需要一些横切关注点(Cross-Cutting Concerns)的功能:

  • SQL性能监控:记录每条SQL的执行时间

  • 分页处理:自动为查询语句添加分页参数

  • 数据权限过滤:根据用户权限自动添加数据过滤条件

  • SQL改写:优化或调整生成的SQL语句

  • 敏感数据加密/解密:在参数设置和结果获取时进行数据转换

如果将这些功能硬编码到框架核心中,会导致代码臃肿且难以维护。插件机制正是为了解决这个问题而生的——它允许在不修改框架源码的情况下,通过外部插件来扩展和增强框架功能。

三、插件机制深度解析:四大可拦截对象

MyBatis的插件可以拦截四大核心组件的方法执行,这也是插件机制的强大之处:

  1. Executor:这是最常被拦截的对象,可以拦截的方法包括:

    • update():增删改操作的入口

    • query():查询操作的入口

    • commit()rollback():事务相关操作

    • flushStatements():批处理操作 应用场景:实现二级缓存、SQL执行时间监控、批量操作优化等。

  2. StatementHandler:SQL语句执行的核心处理器,可拦截:

    • prepare():创建Statement时

    • parameterize():设置参数时

    • query()update():执行SQL时 应用场景:分页插件(改写SQL)、性能监控、参数加密等。

  3. ParameterHandler:参数处理器,可拦截:

    • setParameters():设置参数到PreparedStatement时 应用场景:参数加密、参数验证、参数默认值设置等。

  4. ResultSetHandler:结果集处理器,可拦截:

    • handleResultSets():处理ResultSet生成结果对象时

    • handleOutputParameters():处理存储过程输出参数时 应用场景:结果集解密、结果集增强、懒加载触发等。

四、插件实现原理:JDK动态代理的责任链模式

MyBatis插件的实现原理相当优雅,它结合了JDK动态代理和责任链模式:


具体实现步骤:

  1. 插件定义:开发者实现Interceptor接口,定义拦截逻辑:

     @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})public class MyPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 前置处理System.out.println("Before method: " + invocation.getMethod().getName());// 执行原始方法Object result = invocation.proceed();// 后置处理System.out.println("After method: " + invocation.getMethod().getName());return result;}}
  2. 代理包装:MyBatis启动时,会通过Plugin.wrap()方法,使用JDK动态代理为目标对象创建代理: 

    public static Object wrap(Object target, Interceptor interceptor) {// 创建代理对象,将所有方法调用路由到interceptor.intercept()return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new Plugin(target, interceptor));}
  3. 责任链构建:当有多个插件时,MyBatis会构建一个代理链:

     // 伪代码:多个插件的包装过程Object target = new SimpleStatementHandler(...);target = Plugin.wrap(target, plugin1);target = Plugin.wrap(target, plugin2);target = Plugin.wrap(target, plugin3);// 最终使用的target已经是经过三层代理的对象
  4. 方法拦截:当调用代理对象的方法时,会触发Plugin.invoke(),进而调用插件的intercept()方法。在intercept()中,开发者可以决定是否继续调用invocation.proceed()来执行链中的下一个拦截器或最终的目标方法。

五、总结与展望

通过本阶段的开发,我们不仅实现了一个功能完整的ORM框架,更重要的是理解了MyBatis架构演进的思路:从核心功能实现,到职责分离优化,再到通过插件机制提供扩展性。

插件机制是MyBatis架构中最精妙的设计之一,它体现了"开放-封闭原则"(对扩展开放,对修改关闭)的精髓。通过动态代理和责任链模式的结合,MyBatis提供了一个极其灵活且强大的扩展机制。

在接下来的文章中,我们将深入探讨:

  1. 如何实现一个完整的插件系统

  2. 事务管理的深度集成

  3. 缓存机制的设计与实现

  4. 动态SQL的解析与处理

每一次的架构优化都是为了更好地应对未来的需求变化,这也是软件设计的永恒追求。我们的手写MyBatis之旅,不仅是在"造轮子",更是在深入理解优秀框架背后的设计哲学和实现原理。


💖学习知识需费心,
📕整理归纳更费神。
🎉源码免费人人喜,
🔥码农福利等你领!

💖常来我家多看看,
📕我是程序员扣棣,
🎉感谢支持常陪伴,
🔥点赞关注别忘记!

💖山高路远坑又深,
📕大军纵横任驰奔,
🎉谁敢横刀立马行?
🔥唯有点赞+关注成!

http://www.dtcms.com/a/359244.html

相关文章:

  • Agent实战教程:LangGraph结构化输出详解,让智能体返回格式化数据
  • Keil5 MDK_541官网最新版下载、安装
  • offsetof宏的实现
  • 线程池项目代码细节2
  • 互联网医院系统源码解析:如何从零搭建高效的在线问诊平台
  • SNMPv3开发--EngineID安全访问机制
  • 腾讯云的运维笔记——从yum的安装与更新源开始
  • 深入理解 Linux 驱动中的 file_operations:从 C 语言函数指针到类比 C++ 虚函数表
  • centos7中MySQL 5.7.32 到 5.7.44 升级指南:基于官方二进制包的原地替换式升级
  • 有个需求:切换车队身份实现Fragment的Tab隐藏显示(车队不显示奖赏)
  • SNMPv3开发--简单使用
  • 【Linux基础】深入理解Linux环境下的BIOS机制
  • Python - 机器学习:从 “教电脑认东西” 到 “让机器自己学规律”
  • 项目管理和产品管理的区别
  • docker,mysql安装
  • vector的学习和模拟
  • 揭秘表格推理的“思维革命”:RoT模型介绍
  • 【机器学习基础】机器学习中的容量、欠拟合与过拟合:理论基础与实践指南
  • Vue生命周期、工程化开发和脚手架、组件化开发
  • 学习日志41 python
  • 打工人日报#20250830
  • 内网后渗透攻击--跨域攻击
  • 给某个conda环境安装CUDA 12.4版本 全局CUDA不变
  • Mybatis 动态sql
  • 【树形数据结构】李超线段树 (Li-Chao Tree)
  • 【深度学习新浪潮】有没有什么方法可以将照片变成线描稿,比如日式漫画的那种?
  • 嵌入式学习日记(38)HTTP
  • Ansible主机模式与文件导入技巧
  • 开发环境全面配置指南:语言环境与数据库工具
  • 【面试场景题】订单超时自动取消功能如何设计