一、前言
昨天,一个同事Eclipse在启动SpringBoot项目时一直不停地加载,后来发现是因为spring-boot-devtools造成的问题,因为我们把日志输出的目录设置在当前项目里(~/mnt/logs/,这样设置是因为mac电脑没有根目录权限),devtools检测到了项目中文件的变更就不停地加载,今天我们来介绍一下devtools的配置和原理。
二、IDEA配置devtools
spring-boot-devtools是一个为开发者服务的模块,可以实现SpringBoot项目热部署。
1、添加依赖包
2、IDEA配置支持热部署
配置自动编译
配置重启应用
然后你修改类应用就会立即重启生效,比手工重启要快很多。
三、devtools的原理
基本原理是使用了两个ClassLoader,一个ClassLoader加载那些不会改变的类(第三方Jar包),另一个ClassLoader加载会更改的类,称为restart ClassLoader,在代码更改时原来的restart ClassLoader会被丢弃,重新创建一个restart ClassLoader,由于需要被加载的类比较少,所以实现较快的重新加载。
核心流程如下
1、spring.factories
注:spring启动时会扫描spring.factories并且注册事件监听器RestartApplicationListener
2、RestartApplicationListener
监听到RestartApplicationListener事件后,另外启动一个线程使用RestartClassLoader来加载Main函数,将原来主线程Hold住。
调用栈如下:
关键代码如下:
注:新启动一个线程执行runnable, 执行完成以后会join(),hold住主线程.
注:创建RestartClassLoader
注:Hold线程
注:使用RestartClassLoader来加载Main启动类。
3、监听文件变化后进行重启
ClassPathFileSystemWatcher 实现了InitializingBean,在初始化的时候会调用fileSystemWatcher.addListener创建一个监听器,并启动文件改变监听线程。
文件监控类FileSystemWatcher启动线程扫描文件的变化,如果文件有变化发送通知。
ClassPathFileChangeListener.onChange()会被调用,最终
LocalDevToolsAutoConfiguration.
RestartingClassPathChangeChangedEventListener的
onApplicationEvent会被调用。