自己做的网站可以查看谁访问吗,网店美工教案,杭州关键词优化外包,图片制作动画文章目录 1. 常见的几种实现代码热更新的几种方式对于开发环境我们可以使用部署环境1. 使用 Arthas 的 redefine 命令来加载新的 class 文件2. 利用 URLClassLoader 动态加载3. 通过Java的Instrumentation API 也是可以实现的 2. 实现1. ClassScanner扫描目录和加载类2. 定时任… 文章目录 1. 常见的几种实现代码热更新的几种方式对于开发环境我们可以使用部署环境1. 使用 Arthas 的 redefine 命令来加载新的 class 文件2. 利用 URLClassLoader 动态加载3. 通过Java的Instrumentation API 也是可以实现的 2. 实现1. ClassScanner扫描目录和加载类2. 定时任务定时加载指定路径下的类使用上面的ClassScanner3. 在Spring配置中启用定时任务并添加ClassScanner 1. 常见的几种实现代码热更新的几种方式
对于开发环境我们可以使用
Spring Boot DevtoolsJRebel 插件IDEA的Debug 模式的热更新
部署环境
但是对于生产环境我们想要更新替换某个类 则无法使用上面几种方式目前我知道的有如下几种
1. 使用 Arthas 的 redefine 命令来加载新的 class 文件
bash
$ redefine /home/admin/User.class其中/home/admin/User.class 是你上传的新 class 文件的路径。Arthas 会立即加载新的 class 文件你的应用会立即使用新的代码逻辑。值得注意的是 这种方式只适合修改方法内的代码逻辑不适合增加方法或者修改方法签名否则可能会引发 NoSuchMethodError 或 ClassFormatError 等错误。 这种方式只是临时更新 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;Autowiredpublic 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 {Autowiredprivate ApplicationContext applicationContext;Beanpublic ClassScanner classScanner() {return new ClassScanner(/tmp/classes, applicationContext);}
}