使用反射和动态代理实现mybaits的mapping.xml热部署

6.5热部署修改xml不重启 立即下载
package com.apexsoft.citic.managed.assistance.module.backdoor.service;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;


@Service
public class BackdoorService {

    private static Logger log = Logger.getLogger(BackdoorService.class);

    @Resource
    SqlSession sqlSession;

    private static long lastRefreshMapperTime = System.currentTimeMillis();
    private static boolean isModifiedStrictMapOfConfiguration = false;

    public Set<String> refreshMappper() throws NoSuchFieldException, IllegalAccessException, IOException {
        long startRefreshMapperTime = System.currentTimeMillis();
        Configuration configuration = sqlSession.getConfiguration();
        Field loadedResourcesField = configuration.getClass().getDeclaredField("loadedResources");
        loadedResourcesField.setAccessible(true);
        Set<String> loadedResources = (Set<String>) loadedResourcesField.get(configuration);
        Set<String> loadedResourcesBak = new HashSet<String>(loadedResources);
        Set<String> refreshedResources = new HashSet<String>();
        for (String resource : loadedResourcesBak) {
            if (resource.endsWith(".xml") && isNeedRefresh(resource)) {
                loadedResources.remove(resource);
                if(!isModifiedStrictMapOfConfiguration){
                    modifyStrictMapOfConfiguration(configuration);
                }
                //使用classloader.getResource().openStream() 可以清除缓存
                InputStream inputStream = Thread.currentThread().getContextClassLoader().getResource(resource).openStream();
                XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
                mapperParser.parse();
                refreshedResources.add(resource);
            }
        }
        lastRefreshMapperTime = startRefreshMapperTime;
        return refreshedResources;
    }

    private synchronized void modifyStrictMapOfConfiguration(Configuration configuration) throws NoSuchFieldException, IllegalAccessException {
        if (!isModifiedStrictMapOfConfiguration){
            isModifiedStrictMapOfConfiguration = true;
            // 清理原有资源,更新为自己的StrictMap方便,增量重新加载
            String[] mapFieldNames = new String[]{"mappedStatements", "caches", "resultMaps", "parameterMaps", "keyGenerators", "sqlFragments"};
            for (String fieldName : mapFieldNames) {
                Field field = configuration.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                Map map = ((Map) field.get(configuration));
                InvocationHandler invocationHandler = new StrictMapInvocationHandler(map);
                Map mapProxy = (Map)Proxy.newProxyInstance(map.getClass().getClassLoader(), map.getClass().getSuperclass().getInterfaces(), invocationHandler);
                field.set(configuration, mapProxy);
            }
        }
    }
    
    private boolean isNeedRefresh(String resource) {
        String nodepath = this.getClass().getClassLoader().getResource("/").getPath();
        File file = new File(nodepath + resource);
        if (file.lastModified() < lastRefreshMapperTime) {
            return false;
        }
        return true;
    }

    protected class StrictMapInvocationHandler implements InvocationHandler{

        private Map target;

        public StrictMapInvocationHandler(Map target){
            super();
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(method.getName().equals("put")){
                String key = args[0].toString();
                target.remove(key);
                log.info("refresh key:" + key.substring(key.lastIndexOf(".") + 1));
            }
            return method.invoke(target, args);
        }
    }
}

ps: 目前代码只是实现了mapping.xml的重新加载,可以作为java热部署技术的补充

IntelliJ IDEA修改了mybatis mapper xml后不用重启tomcat,自动热发布 热更新 热部署.zip IntelliJ IDEA修改了mybatis mapper xml后自动热发布 热更新 热部署.zip Mybatis xml文件使用热加载检测不更新怎么办?看我的 立即下载

相关推荐

Windows下Colmap编译安装全攻略:从Boost到CUDA的避坑指南

本文详细介绍了在Windows系统下编译安装Colmap三维重建工具的完整流程与实战经验。针对Boost库版本兼容性、CUDA与Visual Studio的版本匹配等常见难题提供了具体的避坑指南和解决方案,帮助开发者高效完成从环境配置到最终部署的全过程。

weixin_28235513的博客 199

用反射手写mybatis全注解实现(反射真实应用)

反射手写 mybatis 全注解实现(反射真实应用) 为了简化代码部分操作省略,只为突出反射思想和概念 Q & A Q mybatis为我们做了哪些事? 配置文件有何作用? 为什么用到反射? A  mybatis 讲我们的查询结果自动封装到实体类。 配置文件可以解耦,我们想把mysql驱动换成oracle驱动只需要修改配置文件即可。 由于我们不知道用到哪个实体类封装数据,所以这个过程是动态的。我们需要动态获取类信息,进行动态封装

三少说 701

树莓派安装snowboy

1、树莓派换源 参考链接:https://blog.csdn.net/qq_43556844/article/details/113615915 2、更新pip3 参考链接:https://blog.csdn.net/qq_43556844/article/details/113616214 3、存取麦克风 我们使用PortAudio作为音频输入/输出的跨平台支持。我们还使用sox作为快速实用程序来检查麦克风设置是否正确。 sudo apt-get install python-pyaudio python

qq_43556844的博客 1923

idea使用jrebel热部署修改mapper.xml中SQL代码仍然有效方案

使用idea2020.1版本加jrebel2022.4.1版本

qq_45621643的博客 1727

【技术实战】SeaTunnel 实现 HTTP 到 Doris 数据同步的配置优化与问题解决

本文分享了使用SeaTunnel实现HTTP数据源到Doris数仓同步的实战经验。详细解析了从环境搭建、核心配置到生产部署的全流程,重点针对数据类型映射、分页拉取、依赖冲突等典型问题提供了解决方案,并给出了连接参数调优、错误处理等进阶优化技巧,帮助开发者构建稳定高效的数据同步管道。

gan8painter的博客 752

保姆级教程:用Docker一键部署vLLM大模型推理服务(附常见报错解决方案)

本文提供了一份详细的Docker化vLLM大模型推理服务部署指南,涵盖从环境准备到性能调优的全流程。通过容器化技术解决大语言模型部署中的显存利用率、吞吐量等核心问题,并附常见报错解决方案,帮助开发者快速构建高效、可扩展的AI推理服务。

weixin_29248313的博客 492

Mybatis3.5.4源码分析-3- 获取mapper,反射调用查询

BlogMapper mapper = session.getMapper(BlogMapper.class); mybatis中,通过session.getMapper来获取mapper接口的实现类,同样的,ctrl+alt+B 进入这个方法的默认实现 org.apache.ibatis.session.defaults.DefaultSqlSession#getMapper 中: @Override public <T> T getMapper(Class<T> t.

weixin_41300437的博客 1592

EETI_eGTouch驱动移植及校准

一.环境 芯片:NXP IMX6Q 内核版本:4.1.15 uname:Linux myimx6ek314 4.1.15-myimx6-g5d588fa6-dirty #4 SMP PREEMPT Tue Nov 17 17:26:34 CST 2020 armv7l armv7l armv7l GNU/Linux 二.官方《EETI_eGTouch_Linux_Programming_Guide_v2.5l.pdf》文档勘误 HID_MULTITOUCH =Y or N(官方文档设置为M): 正确设置H

Garden的博客 4334

反射和代理以及Mapper中的应用

java中的反射和代理, 反射和代理在Mybatis Mapper中的使用

weixin_44715126的博客 1219

3.DJI-payload SDK自定义控件的设计:

自定义控件(Widget)是指负载运行时,在用户界面中显示的自定义 UI 控件,以帮助用户快速查看负载独特的设备状态,或者对负载设进行设置。这些 UI 控件可以显示在以下用户界面中。Pilot 2 应用程序;大疆智图;基于 MSDK 开发的应用程序。这种自定义控件并不是通过 MSDK 实现的,而是通过 PSDK 的配置实现的。。

哒宰的博客 770

增益调度控制 —— 理论、案例与交互式 GUI 实现

本文详细介绍了增益调度控制的基本原理、数学模型及公式推导,探讨了该方法在适应非线性系统和大范围工作条件下的优势与局限。通过航空飞行控制、发动机推力控制以及化工过程控制三个典型案例,我们展示了如何利用调度变量动态调整控制增益,从而使得控制系统在各个工作点均能达到优良性能。为帮助工程师和研究者更直观地理解并验证增益调度控制的实际效果,本文提供了一套基于 Python 与 PyQt6 的交互式 GUI 控制系统代码。用户不仅可以实时查看仿真数据,还能通过在线调节参数直观体验调度控制的优势。

闲人编程的博客 1480

Mybatis反射实现装载Mapper

啥地方

xdkb159的博客 2308

Python 爬虫实战:雪球用户数据爬取与投资行为分析(含 API 签名算法解析)

雪球作为国内领先的投资者社区,拥有丰富的用户数据和投资信息。通过爬取雪球用户数据并进行分析,我们可以深入了解用户的持仓偏好、交易行为和投资策略,为企业和投资者提供有价值的市场洞察。

yansideyucsdn的博客 2246

JRebel热部署,解决修改mapper的xml文件不生效的问题

JRebel热部署,解决修改mapper的xml文件不生效的问题

咸鱼想睡觉 2483

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

springboot+mybatis热启动

參考:https://blog.csdn.net/angry_mills/article/details/80565863 springboot 2.0.0.RELEASE mybatis3.4.5 mybatis-spring-boot-starter1.3.0 MapperRefresh类有点小改动: package cn.com.do1.co...

juane的专栏 702

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

IDEA + Spring Boot + JRebel + MyBatis Mapper XML 热部署不能自动编译的解决方案和启动的几种方式

自动编译 方式一:Srping Boot Application 类 方式二:org.springframework.boot Maven/Gradle 插件 方式三:Tomcat MyBatis Mapper XML 热部署

欲穷三千界 2万+

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

实现项目启动之后,修改Mapper XML内容不用重启即可生效(mapper文件热部署)

在日常开发中,如果启动项目后,再次修改Mapper XML文件,必须重启服务才能生效,这样就大大影响了我们的开发效率。在近期接触到的项目里面,有个这个功能,趁着假期,查了些资料,将里面的用法拿出来,记录一下: 具体的源码还没来得及研究,水平有限,也看不懂源码。。。。。。。。。。 实际就是重写了mybatis的加载xml文件的方法 这里重建一个完整的maven-demo,顺便记录一下maven搭建w...

种一棵树最好的时间是十年前,其次是现在。 2万+

mybatis mapper xml文件热部署

针对网上关于mybatis mapper xml文件的热部署进行一个总结: 第一种方式:只要改动相应的mapper xml文件就全部扫描 第二种方式:只针对修改了的mapper xml文件进行重新加载 下面就针对这两种方式详细介绍 方式一: 创建一个MapperRefresh的java工具类 package com.thinkgem.jeesite.mybatis.thre

engineer_hzl 3296

Mybatis实现*mapper.xml热部署-分子级更新

无意中发现了一个巨牛的人工智能教程,忍不住分享一下给大家。教程不仅是零基础,通俗易懂,而且非常风趣幽默,像看小说一样!觉得太牛了,所以分享给大家。点这里以跳转到教程。 需求: 项目在开发阶段或是修复bug阶段,会有修改mybatis的mapper.xml的时候,修改一般情况都要重启才能生失效,如果是分布式项目重启有时会耗时很久,都是无尽的等待。如果频繁修改,那么时间都浪费到等待重启的过程。 ...

程序员的蜕变 2万+

mybatis热部署加载*Mapper.xml文件

文章内容下周整理

CS568591377的专栏 1万+

mybatis热部署加载*Mapper.xml文件,手动刷新*Mapper.xml文件

由于项目已经发布到线上,要是修改一个Mapper.xml文件的话,需要重启整个服务,这个是很耗时间的,而且在一段时间内导致服务不可用,严重影响用户 的体验度。所以希望可以有一个机制可以,当修改某个mapper.xml的时候,只要重新加载这个mapper.xml就好了,参考网上的一些资料和demo,加上一些 自己的总结,下面的代码是通过测试的,可以供你们参考和使用。 import java.i

一不小心的程序员 1万+

Mybatis中的反射和动态代理

Mybatis的运行分为两个部分,第一部分是读取配置文件缓存到Configuration对象,用以创建SqlSessionFactory,第二部分是SqlSession的执行过程。相对而言,SqlSessionFactory的创建比较容易理解,而SqlSession的执行过程远远不是那么简单了,它将包括许多复杂的技术,我们需要先讨论反射技术和动态代理技术,这是揭示mybatis底层架构的基础。

徐小百的博客 7488

Java实现文件变化监听

在平时的开发过程中,会有很多场景需要实时监听文件的变化,如下通过实时监控mysql的binlog日志实现数据同步修改配置文件后,希望系统可以实时感知应用系统将日志写入文件中,日志监控系统可以实时抓取日志,分析日志内容并进行报警类似ide工具,可以实时感知管理的工程下的文件变更定时任务+File#lastModified在Java7中新增了,通过它可以实现文件变动的监听。只能监听当前目录下的文件和目录,不能监视子目录。commons-io对实现文件监听的实现位于;...

Shawn的个人博客 7077

深入浅出MyBatis:反射和动态代理

前三篇详细总结了Mybatis的基本特性、常用配置、映射器,相对于Hibernate,映射器的配置相对复杂,但有很好的灵活性和扩展性,可以应对各种业务场景。熟练掌握这些内容,可以流畅的使用MyBatis进行开发了。 后面准备介绍MyBatis的解析和运行原理以及自定义插件,今天看了书籍的这部分,都会涉及到反射和动态代理这些基础,本篇文章总结下这些,便于理解原理。 通过本篇的介绍,你会了解...

weixin_34466348的博客 1110

Spring学习——手动实现Mapper.xml文件的热部署

原文转载自:https://blog.csdn.net/lovelong8808/article/details/78738086   转载使用后,根据实际情况有做部分修改,感谢原文博主提供的刷新方法。 注意,目前该方法只支持全量刷新,即刷新指定路径下的所有Mapper.xml文件,不支持仅刷新修改后的部分Mapper.xml。   由于项目已经发布到线上,要是修改一个Mapper.xm...

_修铁路的、的博客 1778
上一篇: 学习mybatis源码疑惑一
拓-拓
博客等级 码龄12年 10粉丝 14原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值