自定义热加载:如何不停机实现核心代码更新

news2025/1/23 3:50:30

文章目录

  • 1. 常见的几种实现代码热更新的几种方式
      • 对于开发环境我们可以使用
      • 部署环境
        • 1. 使用 Arthas 的 redefine 命令来加载新的 class 文件
        • 2. 利用 URLClassLoader 动态加载
        • 3. 通过Java的Instrumentation API 也是可以实现的
  • 2. 实现
    • 1. ClassScanner扫描目录和加载类
    • 2. 定时任务定时加载指定路径下的类,使用上面的ClassScanner:
    • 3. 在Spring配置中启用定时任务并添加ClassScanner:

在这里插入图片描述

1. 常见的几种实现代码热更新的几种方式

对于开发环境我们可以使用

  1. Spring Boot Devtools
  2. JRebel 插件
  3. IDEA的Debug 模式的热更新

部署环境

但是对于生产环境我们想要更新替换某个类 则无法使用上面几种方式,目前我知道的有如下几种

1. 使用 Arthas 的 redefine 命令来加载新的 class 文件
```bash
$ redefine /home/admin/User.class
```
其中,`/home/admin/User.class` 是你上传的新 class 文件的路径。

Arthas 会立即加载新的 class 文件,你的应用会立即使用新的代码逻辑。值得注意的是,
这种方式只适合修改方法内的代码逻辑,不适合增加方法或者修改方法签名,否则可能会引发 NoSuchMethodErrorClassFormatError 等错误。
这种方式只是临时更新 JVM 中的字节码,如果应用重启,修改的内容会丢失。因为这种方式可能带来一些风险,所以在生产环境中使用时需要谨慎。

2. 利用 URLClassLoader 动态加载

今天我们利用URLClassLoader 写一个简单的工具程序,内置到我们的应用中,方便我们在不停服务的情况下快速在发布环境验证我们的功能或者修复bug.

3. 通过Java的Instrumentation API 也是可以实现的

Instrumentation是Java语言中的一个API,它提供了一种在程序运行时监测、管理和修改Java字节码的能力。它允许开发者通过编程方式访问和操作类定义、方法和对象,从而实现各种动态的、非侵入式的操作。

这个不是我们今天的重点,我们今天通过URLClassLoader 和Spring 集成实现一个热加载工具。

2. 实现

1. ClassScanner扫描目录和加载类

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;

public class ClassScanner {
    private final String classPath;
    private final ApplicationContext applicationContext;

    public ClassScanner(String classPath, ApplicationContext applicationContext) {
        this.classPath = classPath;
        this.applicationContext = applicationContext;
    }

    public void scanAndLoad() throws Exception {
        // 获取并遍历目录下的所有文件
        File dir = new File(classPath);
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                // 只处理 .class 文件
                if (file.isFile() && file.getName().endsWith(".class")) {
                    // 加载类
                    String className = file.getName().substring(0, file.getName().length() - 6);
                    URL[] urls = new URL[]{dir.toURI().toURL()};
                    try (URLClassLoader loader = new URLClassLoader(urls)) {
                        Class<?> clazz = loader.loadClass(className);
                        // 将类的实例添加到 Spring 容器
                        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
                        beanFactory.autowireBean(clazz.newInstance());
                    }
                }
            }
        }
    }
}

2. 定时任务定时加载指定路径下的类,使用上面的ClassScanner:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScannerTask {
    private final ClassScanner classScanner;

    @Autowired
    public ScannerTask(ClassScanner classScanner) {
        this.classScanner = classScanner;
    }

    @Scheduled(fixedRate = 5000)
    public void scan() throws Exception {
        classScanner.scanAndLoad();
    }
}

3. 在Spring配置中启用定时任务并添加ClassScanner:

每隔5秒,Spring就会执行一次ScannerTask.scan()方法,扫描目录并加载找到的类。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableScheduling;
import org.springframework.context.ApplicationContext;

@Configuration
@EnableScheduling
public class AppConfig {
    @Autowired
    private ApplicationContext applicationContext;

    @Bean
    public ClassScanner classScanner() {
        return new ClassScanner("/tmp/classes", applicationContext);
    }
}

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

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

相关文章

system trace

adb shell stopadb shell start //重启adb 数据会干净点adb shell //也试过在adb shell 外面dump system trace&#xff0c;但是同样的参数dump出来看不到如此详细&#xff0c;比如makeApplication的时长&#xff0c;线程执行被中断等atrace -z -b 40000 am wm view res ss g…

常用接口测试工具

首先&#xff0c;什么是接口呢&#xff1f; 接口一般来说有两种&#xff0c;一种是程序内部的接口&#xff0c;一种是系统对外的接口。 系统对外的接口&#xff1a;比如你要从别的网站或服务器上获取资源或信息&#xff0c;别人肯定不会把数据库共享给你&#xff0c;他只能给你…

如何使用ASO优化来提高应用的安装率

应用程序的成功并非一蹴而就&#xff0c;它需要大量的时间和工作&#xff0c;而这一切都取决于对流程的深入理解、对结果的衡量以及对执行的某些营销活动的有效性进行分析。但哪些优化在App Store或Google Play上取得成功最关键&#xff1f;为了取得成功&#xff0c;我们必须跟…

2023/9/27 -- ARM

【汇编语言相关语法】 1.汇编语言的组成部分 1.伪操作&#xff1a;不参与程序的执行&#xff0c;但是用于告诉编译器程序该怎么编译 .text .global .end .if .else .endif .data2.汇编指令 编译器将一条汇编指令编译成一条机器码&#xff0c;在内存里一条指令占4字节内…

服务断路器_Resilience4j重试机制

重试机制比较简单&#xff0c;当服务端处理客户端请求异常时&#xff0c;服务端将会开启重试机制&#xff0c;重试期间内&#xff0c;服务端将每隔一段时间重试业务逻辑处理。 如果最大重试次数内成功处理业务&#xff0c;则停止重试&#xff0c;视为处理成功。如果在最大重试次…

手动关闭Spring定时任务

一、问题 比如我写了一个这样的定时任务类&#xff0c;该定时任务很简单&#xff1a;每秒打印一行craneing… 那么后期我想中途关闭和开启这个定时任务应该怎么处理&#xff1f; 二、解决 spring定时任务依赖 ThreadPoolTaskScheduler 这个类&#xff0c;我们只需要顶掉这个…

UE蓝图学习(从Unity3D而来)

一、UE组件对比Unity3D&#xff0c;从Unity3D过渡来学的角度出发&#xff0c;可以理解为在 空物体下放置子物体。UE没有U3D那种可以将组件挂在自身空物体上面。 二、UE 蓝图的情境提示&#xff0c;必须先找到相应的类型&#xff0c;对象对象、事件事件&#xff0c;才能找到相应…

案例题概述

案例题概述 考点 考点 新教材的新增考点 第一题必做&#xff0c;之后是4选2 感觉都是记忆的&#xff0c;课件完整一些&#xff0c;之后以看课件为主了&#xff0c;不在做详细笔记了

Scrapy框架Splash渲染

Scrapy框架是一款强大而灵活的Python网络爬虫框架&#xff0c;用于快速、高效地爬取和提取网页数据。然而&#xff0c;对于一些使用动态渲染技术的网站&#xff0c;Scrapy在处理JavaScript生成的内容上可能会有些困难。为了应对这种情况&#xff0c;Scrapy提供了Splash渲染服务…

数码产品数码配件无线键盘等出口欧盟CE-RED认证测试办理

数码产品数码配件无线键盘CE-RED认证测试办理 无线产品CE-RED认证进入东欧市场规定&#xff1a; 在通信终端设备和无线产品在这些/地区合法销售之前&#xff0c;必须按照 RED 指令进行测试&#xff0c;并且还必须提供 CE 标志。无线远程控制产品必须符合 RED 指令的 REDEU 要…

unittest单元测试框架使用

什么是unittest 这里我们将要用的unittest是python的单元测试框架&#xff0c;它的官网是 25.3. unittest — Unit testing framework — Python 2.7.18 documentation&#xff0c;在这里我们可以得到全面的信息。 当我们写的用例越来越多时&#xff0c;我们就需要考虑用例编写…

油猴(篡改猴)学习记录

第一个Hello World 注意点:默认只匹配了http网站,如果需要https网站,需要自己添加match https://*/*代码如下 这样子访问任意网站就可以输出Hello World // UserScript // name 第一个脚本 // namespace http://tampermonkey.net/ // version 0.1 // descri…

2023/9/26 -- ARM

【计算机相关理论】 1.计算机的组成 输入设备、输出设备、存储器、运算器、控制器 1.输入设备&#xff1a;将编写好的软件代码以及相关的数据输送到计算机中。转换成计算机可以识别、存储 和处理的数据。 例如&#xff1a;鼠标、键盘、复印机、传感器 2.输出设备&a…

结构型设计模式——组合模式

摘要 组合模式(composite pattern): 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合。 一、组合模式的意图 将对象组合成树形结构来表示“整体/部分”层次关系&#xff0c;允许用户以相同的方式处理单独…

【Java SE】Lambda表达式

目录 ♫什么是Lambda表达式 ♫Lambda表达式的语法 ♫函数式接口 ♫Lambda表达式的使用 ♫变量捕获 ♫ Lambda表达式在集合中的使用 ♪Collection的foreach()&#xff1a; ♪List的sort()&#xff1a; ♪Map的foreach() ♫什么是Lambda表达式 Lambda 表达式是 Java SE 8中一个…

Socks5代理IP是什么?有什么优点及如何使用?

随着网络威胁和数据泄露的数量不断增加&#xff0c;在浏览互联网时保护个人信息并保持匿名变得至关重要。实现此目的的一种有效方法是使用Socks5代理IP。如今Socks5代理被广泛应用于跨境电商/社媒平台、SEO业务、网络抓取等领域&#xff0c;在这篇文章中&#xff0c;我们将讨论…

服务好的CMDB运维管理平台的服务优势

随着公司信息化程度的不断提高&#xff0c;IT基础设施也越来越复杂。为了方便这些基础设施的管理和维护&#xff0c;CMDB&#xff08;配置管理数据库&#xff09;运维管理平台应运而生。本文将介绍一个服务好、价格实惠的CMDB运维管理平台&#xff0c;帮助读者更好地了解和使用…

扫地机器人经营商城小程序的作用是什么

扫地机器人对人们生活大有帮助&#xff0c;近些年也有不少企业开创品牌&#xff0c;在电商平台每年销量也非常高&#xff0c;同行竞争激烈及私域化程度加深情况下&#xff0c;虽然第三方平台或线下方式也有生意&#xff0c;但互联网电商发展也为商家们带来了诸多痛点。 那么通…

CRM软件系统如何选择部署方式

CRM的部署方式是选型的主要衡量标准&#xff0c;云部署CRM系统指应用程序在技术商的公有云上&#xff0c;本地化部署将应用程序架设在本地基础设施上&#xff0c;享有应用的所有权。那么CRM系统选择云部署还是本地化部署&#xff1f; 1.云部署CRM系统性价比更高 我们知道本地…

HTTP 跨域名请求(CORS)

同源策略 出于安全考虑&#xff0c;浏览器会限制脚本中发起的跨域请求。比如&#xff0c;使用 XMLHttpRequest 对象和Fetch发起 HTTP 请求就必须遵守同源策略。 具体而言&#xff0c;Web 应用程序通过 XMLHttpRequest 对象或Fetch能且只能向同域名的资源发起 HTTP 请求&#x…