spring-boot-devtools 快速重启的秘密!

简介: 上文写了 AOP 插件 后,咱们也了解到这个 ClassLoader 的重要,所以今天咱们来聊聊这个热部署神器 spring-boot-devtools 的源码,看看它是怎么用这个 ClassLoader 来实现快速重启,帮我们节省时间的!😝

网络异常,图片无法展示
|



上文写了 AOP 插件 后,咱们也了解到这个 ClassLoader 的重要,所以今天咱们来聊聊这个热部署神器 spring-boot-devtools 的源码,看看它是怎么用这个 ClassLoader 来实现快速重启,帮我们节省时间的!😝


文章概要


文章的主旋律如下👇


网络异常,图片无法展示
|


spring.factories


在了解了 Springboot 的自动装配原理 后(不了解可以看看 4ye 之前写的这篇 👉


《Springboot自动装配原理探索》),我们直接打开 spring-boot-devtools 源码 ,找


spring.factories 文件,


网络异常,图片无法展示
|


我们一般都本地开发调试的,所以就直接看这个 LocalDevToolsAutoConfiguration 类啦😋


LocalDevToolsAutoConfiguration


可以看到核心点在 重启和重载 👇


网络异常,图片无法展示
|


主角👇


网络异常,图片无法展示
|


我们先来看看这个 重启 中有什么叭😄


重启原理介绍


大概这么一个思路👇 下面就跟着源码分析啦😄(文末有源码重启要点流程图


网络异常,图片无法展示
|


RestartConfiguration


有这么些方法👇


网络异常,图片无法展示
|


从名字上分析,这两个方法应该是重点,逻辑上应该是 有一个 watcher 在盯着


classpath ,如果有变动的话,就触发这个 ClassPathChangedEvent 事件 😝


那么看看这个 watcher 叭 😄


ClassPathFileSystemWatcher


网络异常,图片无法展示
|


可以看到这里就创建了这个 ClassPathFileSystemWatcher 类 👇


网络异常,图片无法展示
|


这里我们注意到它实现了三个接口,经过前面 Spring 文章的学习,咱们知道第一步就该看啥了😄


👉 《16张图解锁Spring的整体脉络》


根据类的初始化,先看看有 static 相关的代码没,接着看 构造器 ,最后就来到这个初


始化方法 afterPropertiesSet 啦😄


这里没有 static 方法,构造器也很简单,就是获取 FileSystemWatcherFactory


ClassPathRestartStrategy 和 监视的文件路径,那么就看看 afterPropertiesSet 写了


什么叭 👇


网络异常,图片无法展示
|


ClassPathFileChangeListener


这个也不复杂,就监听到文件改变后,发布事件 ClassPathChangedEvent


网络异常,图片无法展示
|


FileSystemWatcher


接着就是这个 start 方法啦👇


很明显就是开启一个线程,那么咱们来看看线程中到底在 run 什么🐷


网络异常,图片无法展示
|


找到这个任务类 Watcher 👇


网络异常,图片无法展示
|


可以发现它的任务就是一直 scanpollInterval 默认是 1squietPeriod 默认是 0.4s


意思是每次轮询的时间是 1s ,包含中间休息的 0.4s ,休息事件是来确认文件在这个期间没有再次被改动。


改动了的话会回调 FileChangeListeneronChange ,对应我们上面的这个


ClassPathFileChangeListener ,会去发布事件 ClassPathChangedEvent 😋


ApplicationListener


绕了一大圈,终于描述完了这个监视器 ClassPathFileSystemWatcher ,同时,我们也


得把目光移到这个RestartConfiguration 的第二个核心 监听器 👇


如图所示,这个方法的作用就是重启应用 restart


网络异常,图片无法展示
|


重启应用


重启的过程中呢,包括两个步骤,第一步 stop ,第二步 start


stop 部分就是毁灭这些东西了,这里也藏了很多细节,有很多并发相关的知识点 😋

比如


一. ReentrantLock 是写在 try catch 的里面还是外面?


二. 循环里的 rootContexts 其实是 CopyOnWriteArrayList 类型的


三. 通过强制的 OOM 来清除所有的 软/弱引用 (😱 还有这种操作的!)


网络异常,图片无法展示
|


start 的过程中,是通过创建这个重启线程RestartLauncher 来实现的,可以发现该


类的任务就是找到 mainclass 并调用 main 方法,完成重启。


网络异常,图片无法展示
|


而在这个过程中,就涉及到这个 classloader 啦。


ClassLoader


细心的小伙伴可以发现上面这行代码中,调用到了这个 ClassLoader ,这个


getContextClassLoader() 是属于 Thread 类的,通过它可以获取到当前线程上下文的


ClassLoader


Class.forName(this.mainClassName, false, getContextClassLoader());
复制代码


在创建这个 RestartLauncher 线程时,就已经将咱们这个 RestartClassLoader 给传进来了。


网络异常,图片无法展示
|


网络异常,图片无法展示
|


重启时,就直接通过 RestartClassLoader 去找到 main 方法,完成重启。


网络异常,图片无法展示
|


很明显这里 破坏了双亲委派机制,先从自身查找,没有的话再去父类查找


这里 业务代码 都被 RestartClassLoader 加载了,而每次重启都会重新创建这个


RestartClassLoader ,然后去加载业务代码 🐖 (通过传进来的 URL 可以发现)


那么到此,这个 重启 的过程就完成了。


差点忘了,这里还有个默认的监视范围🐷


监视策略


如下图👇 默认策略中,这些路径下的文件变化不被检测


网络异常,图片无法展示
|


可通过配置修改


spring.devtools.restart.exclude=static/**,public/**
复制代码


总结


通过阅读源码,我们知道了 spring-boot-devtools 是通过自定义 RestartClassLoader


来加载业务代码,并在重启时销毁它,再重新创建,进而重新获取代码,实现这个快速


重启的。


而其他 jar 包等由另外的 ClassLoader 加载,不受影响。


同时,也可以看到 Spring 事件机制 无处不在的身影,还有各种初始化的操作,以及线


程,并发,锁在重启过程中的使用,这些就需要小伙伴们打开源码自身感受了,如 守护


线程ReentrantLockCopyOnWriteArrayListCountDownLatch ,甚至 OOM


都能这么用!


还有 重启 原来就是 反射调用 main 方法 呀🐷


重启过程源码要点


网络异常,图片无法展示
|


网络异常,图片无法展示
|


目录
相关文章
|
Java Windows Spring
java实现spring boot项目启动时,重启Windows进程
java实现spring boot项目启动时,重启Windows进程
505 0
|
Java jenkins 持续交付
Spring Boot 项目脚本(启动、停止、重启、状态)
此脚本用来管理 SpringBoot 项目的进程状态。 有提示功能。 把脚本丢到项目文件夹, 添加执行权限即可。 如果 jenkins 使用这个脚本, 需要在 java -jar 命令前添加 BUILD_ID=dontKillMe , 不然 jenkins 会杀掉进程。
465 0
Spring Boot 项目脚本(启动、停止、重启、状态)
|
Java Nacos 开发工具
【有奖问答】- Spring Cloud Alibaba Nacos Feign 注册发现,提供者重启服务成功后导致消费者前几秒调用不成功?
【有奖问答】- Spring Cloud Alibaba Nacos Feign 注册发现,提供者重启服务成功后导致消费者前几秒调用不成功?
204 0
|
Web App开发 Java Spring
Spring Boot 修改静态资源一定要重启项目才会生效吗?未必!
Spring Boot 修改静态资源一定要重启项目才会生效吗?未必!回顾热部署Spring Boot 中的热部署相信大家都用过吧,只需要添加 spring-boot-devtools 依赖就可以轻松实现热部署。
1437 0
|
存储 Java Maven
spring boot修改代码后无需重启设置,在开发时实现热部署
Spring Boot在开发时实现热部署(开发时修改文件保存后自动重启应用)(spring-boot-devtools) 热部署是什么 大家都知道在项目开发过程中,常常会改动页面数据或者修改数据结构,为了显示改动效果,往往需要重启应用查看改变效果,其实就是重新编译生成了新的Class文件,这个文件里记录着和代码等对应的各种信息,然后Class文件将被虚拟机的ClassLoader加载。
2450 0
|
Java Spring
Spring Boot 使用JSP时,修改JSP不生效,需要重启的问题
问题描述 公司项目用的Spring Boot,自己也就对他多研究一些,之前自己练习的Spring Boot项目,都是使用的JSP,在修改后直接刷新页面就可以看到效果,今天升级Spring Boot版本后,发现修改JSP后直接刷新页面没有用了。
1743 0
|
2月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
27天前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
141 2
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
27天前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
47 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块