如何优雅的实现一个Mybatis插件

news2024/9/30 3:22:59

定位:此篇尝试用另一种角度描述如何完成一个mybatis插件,全程可以按段落跳跃阅读,有任何不适欢迎指出Thanks♪(・ω・)ノ

为什么这么设计

如果我想实现一个orm增强插件,首先就应该避免硬编码,最好与业务代码无关。那么就要看看orm框架有没有什么拓展点了。
为了易用,配置越简单越好,要么引入外部配置中心,或者自定义ThreadLocal读取配置。

符合上面这些的,不就是PageHelper吗?
那么自己实现也就方便了,参考PageHelper的思路就可以了

如何增强

这就不得不讲到责任链了,mybatis把所有插件插入到
org.apache.ibatis.session.Configuration#interceptorChain中,等到时候得时候,就返回责任链,

想怎么增强,自己在interceptor中实现即可。

简单配置

第三方配置就不多说了,自己实现即可。

这里参考下PageHelper是通过ThreadLocal,判断上下文参数来判断是否可以跳过。

简单实现一个

gitee仓库地址:https://gitee.com/Nortyr/allinone

  1. Configuration在初始化的时候创建添加到org.apache.ibatis.session.Configuration#interceptorChain
@Configuration
@DependsOn("com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration")
public class SelfConfiguration  {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @PostConstruct
    public void addPageInterceptor() {
        SelfInteceptor interceptor=new SelfInteceptor();
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            sqlSessionFactory.getConfiguration().addInterceptor(interceptor);
        }
    }
}
  1. 这段代码完全可以不这么复杂你可以理解为除了Object obj=invocation.proceed();都是业务增强代码,随便你怎么实现。我再这里主要完成了2个功能
  • 通过方法名+_SELF走一个自己的查询(完全没用,写着玩)
  • 记录下总共pageHelper和sql执行的总共时间(完全没用,写着玩)

完全没有任何实质性的作用,就是写着玩,你们爱怎么实现怎么实现

@Intercepts(
        {
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        }
)
public class SelfInteceptor implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long start=System.currentTimeMillis();
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameter = args[1];
        ResultHandler resultHandler = (ResultHandler) args[3];
        Executor executor = (Executor) invocation.getTarget();
        RowBounds rowBounds = (RowBounds) args[2];

        String msId = ms.getId();
        Configuration configuration = ms.getConfiguration();
        Page page = PageHelper.getLocalPage();
        PageHelper.clearPage();

        String countMsId = msId + "_SELF";
        MappedStatement selfMs=configuration.getMappedStatement(countMsId, false);
        Object countResultList = executor.query(selfMs, parameter,rowBounds, resultHandler);
        System.out.println(countResultList);
        Class clazz= PageMethod.class;
        Method m1 = clazz.getDeclaredMethod("setLocalPage",Page.class);
        m1.setAccessible(true);
        m1.invoke(null,page);
        //注:下面的方法可以根据自己的逻辑调用多次,在分页插件中,count 和 page 各调用了一次
        Object obj=invocation.proceed();
        long end=System.currentTimeMillis();
        System.out.println("恭喜你成功浪费了5分钟。。。。"+(end-start));
        return obj;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

总结

虽然写的很少,但是,PageHelper的底层逻辑应该明白了,就是上面精细化实现没说了,这个应该有别的dalao写过文章了吧,我就懒得写了。再回顾下开篇的2个问题

  • 如何增强
    • 自定义插件加入到interceptorChain中即可,mybatis自己回生成责任链
  • 如何易用
    • PageHelper是通过ThreadLocal实现

gitee地址:https://gitee.com/Nortyr/allinone

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/984192.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C#写一个UDP程序判断延迟并运行在Centos上

服务端 using System.Net.Sockets; using System.Net;int serverPort 50001; Socket server; EndPoint client new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号CreateSocket();void CreateSocket() {server new Socket(AddressFamily.InterNetwork, SocketT…

低代码是程序员“玩”出来的

一、前言 所谓“低代码”&#xff0c;最开始的雏形是程序员写一些重复的东西写腻了&#xff0c;产品今天想加个请假表&#xff0c;明天加个物资申请表&#xff0c;后天又想统计一下记录等等要求。对程序员来说开发这些就是一个个没意思的重复开发工作&#xff0c;所以就想着搞个…

LVGL Animations(动画)的简单使用

一、前言 哈喽&#xff0c;大家好。在进行界面设计的时候&#xff0c;动画的使用是必不可少的&#xff0c;今天这篇文章就跟大家分享一下 LVGL Animations&#xff08;动画&#xff09;的简单使用。笔者将在模拟器上运行演示&#xff0c;LVGL 版本号为 8.3.0。 二、Animation…

【HTML专栏3】!DOCTYPE、lang、字符集的作用

本文属于HTML/CSS专栏文章&#xff0c;适合WEB前端开发入门学习&#xff0c;详细介绍HTML/CSS如果使用&#xff0c;如果对你有所帮助请一键三连支持&#xff0c;对博主系列文章感兴趣点击下方专栏了解详细。 博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;HTML/CS…

当AI遇到IoT:开启智能生活的无限可能

文章目录 1. AI和IoT的融合1.1 什么是人工智能&#xff08;AI&#xff09;&#xff1f;1.2 什么是物联网&#xff08;IoT&#xff09;&#xff1f;1.3 AI和IoT的融合 2. 智能家居2.1 智能家居安全2.2 智能家居自动化 3. 医疗保健3.1 远程监护3.2 个性化医疗 4. 智能交通4.1 交通…

Json“牵手”易贝商品详情数据方法,易贝商品详情API接口,易贝API申请指南

易贝是一个可让全球民众在网上买卖物品的线上拍卖及购物网站&#xff0c;易贝&#xff08;EBAY&#xff09;于1995年9月4日由Pierre Omidyar以Auctionweb的名称创立于加利福尼亚州圣荷塞。人们可以在易贝上通过网络出售商品。2014年2月20日&#xff0c;易贝宣布收购3D虚拟试衣公…

Ros noetic 机器人坐标记录运动路径和发布 实战教程(C)

前言: 承接上一篇博文本文将编写并记录上文中详细的工程项目,用于保存小车的运动路径,生成对应的csv,和加载所保存的路径到实际的Rviz中,本文将开源完整的工程项目,工程结构如下: 工程原码位于文章末尾: 路径存储: waypoint_saver 用于存储 waypoint 的节点 waypo…

控制三盏灯

驱动代码 #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include "head.h"unsigned int major;//保存主设备号 char kbuf[128] {0}; unsigned int …

C# Emgu.CV+Tesseract实现识别图像验证码

效果图&#xff0c;简单的还行&#xff0c;复杂的。。。拉跨 懒得写讲解了&#xff0c;全部源码直接上吧 /// <summary>/// 验证码识别/// </summary>public partial class FrmCodeIdentify : FrmBase{private string _filePath;// 原图像Image<Bgr, byte> …

基于Python开发的DIY字符画程序(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)

一、项目简介 本项目是一套基于Python开发的DIY字符画程序&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含&#xff1a;项目源码、项目文档、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&…

Kafka3.0.0版本——消费者(消费者组初始化流程图解)

一、消费者组初始化流程图解 每个consumer都发送JoinGroup请求&#xff0c;如下图所示&#xff1a; 选出一个consumer作为leader&#xff0c;如下图所示&#xff1a; 把要消费的topic情况发送给leader 消费者&#xff0c;如下图所示&#xff1a; leader会负责制定消费方案…

MFC:自绘CListBox,GetText返回一个乱码

问题描述 自绘CListBox&#xff0c;GetText返回一个乱码&#xff0c;并且还会伴随以下断言 解决方案 ListBox Control 属性【Has Strings】改为True即可

【线程池处理任务】Runnable任务和Callable任务

线程池处理任务 ExecutorService的常用方法 方法名称说明void execute(Runnable command)执行 Runnable 任务Future< T > submit(Callable< T > task)执行 Callable 任务&#xff0c;返回未来任务对象&#xff0c;用于获取线程返回的结果void shutdown()等全部任…

前端,关于一个骚气的页面阅读定位图(菜单)

之前在网上看到一个特别骚气的页面阅读定位菜单&#xff0c;今天给大家分享一下原理&#xff0c;先看效果图&#xff1a; 这是我之前浏览联想官网上看到的一个效果图&#xff0c;觉得相当骚气。然后我把他的背景图扣下来&#xff0c;也做了一个&#xff0c;看看效果。 他的实现…

接口自动化测试总结

一、什么项目适合做自动化测试&#xff1f; 软件需求变动不频繁 测试脚本的稳定性决定了自动化测试的维护成本。如果软件需求变动过于频繁&#xff0c;测试人员需要根据变动的需求来更新测试用例以及相关的测试脚本&#xff0c;而脚本的维护本身就是一个代码开发的过程&#x…

【SpringCloudAlibaba】Seata分布式事务使用

文章目录 分布式事务问题示例Seata概述、官网一个典型的分布式事务过程处理过程全局GlobalTransactional分布式交易解决方案流程图 Seata安装下载修改conf目录下的application.yml配置文件dashboard demo 分布式事务问题示例 单体应用被拆分成微服务应用&#xff0c;原来的三个…

详解Transformer中的Encoder

一.Transformer架构 左半边是Encoder&#xff0c;右半边是Decoder。 二.Vision Transformer Vision Transformer取了Transformer的左半边。包含 Input EmbeddingPositional Encoding多头注意力机制 Add & Norm(前馈网络)Feed Forward Add & Norm 2.1 Input Embe…

C51智能小车(循迹、跟随、避障、测速、蓝牙、wifie、4g、语音识别)总结

目录 1.电机模块开发 1.1 让小车动起来 1.2 串口控制小车方向 1.3 如何进行小车PWM调速 1.4 PWM方式实现小车转向 2.循迹小车 2.1 循迹模块使用 2.2 循迹小车原理 2.3 循迹小车核心代码 3.跟随/避障小车 3.1 红外壁障模块分析​编辑 3.2 跟随小车的原理 3.3 跟随小…

世界级黑客丨电脑犯罪界的汉尼拔

被美国FBI称为电脑界的汉尼拔的人&#xff0c;有什么样的故事&#xff1f; 这个人就是世界级黑客凯文李波尔森&#xff0c;他在早期是正儿八经的黑客&#xff0c;他在17岁的时候就使用TRS-80电脑攻入美国国防部的高等研究计划署网络&#xff0c;但是当时他进去啥也没干&#x…

lambda nodejs 函数降低冷启动时间的最佳实践

lambda nodejs 函数降低冷启动时间的最佳实践 lambda nodejs 函数降低冷启动时间的最佳实践 前言什么是冷启动时间打包服务端 js什么是 inline进一步封装的打包工具存在的弊端以及解决方案Next Chapter完整示例及文章仓库地址 前言 本文章的思路&#xff0c;继承发展自这两篇…