spring-boot-devtools
随着项目的规模扩大,为了解决项目在修改代码后的重启时间过长的问题,在项目中引入了 spring-boot-devtools。
在典型的应用程序开发场景中,开发人员会进行一些更改,然后重新构建项目并启动应用程序以使新更改生效,
spring-boot-devtools 可以让开发人员在修改代码后,无需手动重新启动应用,由该工具自动重新启动应用。
实践
添加如下 Maven 依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
使用IDE 以 --debug
参数启动应用,可以看到如下日志:
20:13:32.110 [Thread-0] DEBUG org.springframework.boot.devtools.restart.classloader.RestartClassLoader - Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@5ed2f852
. ____ ___ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.9)
2023-03-01 20:13:32.970 DEBUG 5868 --- [ restartedMain] o.s.b.devtools.restart.ChangeableUrls : Matching URLs for reloading : [file:/D:/code/spring/test/target/classes/]
2023-03-01 20:13:32.971 DEBUG 5868 --- [ restartedMain] o.s.b.d.settings.DevToolsSettings : Included patterns for restart : []
2023-03-01 20:13:32.971 DEBUG 5868 --- [ restartedMain] o.s.b.d.settings.DevToolsSettings : Excluded patterns for restart : [/spring-boot-starter-[\w-]+/, /spring-boot/(bin|build|out)/, /spring-boot-starter/(bin|build|out)/, /spring-boot-devtools/(bin|build|out)/, /spring-boot-actuator/(bin|build|out)/, /spring-boot-autoconfigure/(bin|build|out)/]
2023-03-01 20:13:36.520 INFO 5868 --- [ restartedMain] tk.lsq27.test.TestApplication: Started TestApplication in 4.395 seconds (JVM running for 5.208)
2023-03-01 20:13:36.527 DEBUG 5868 --- [ restartedMain] o.s.boot.devtools.restart.Restarter : Creating new Restarter for thread Thread[main,5,main]
2023-03-01 20:13:36.527 DEBUG 5868 --- [ restartedMain] o.s.boot.devtools.restart.Restarter : Immediately restarting application
2023-03-01 20:13:36.527 DEBUG 5868 --- [ restartedMain] o.s.boot.devtools.restart.Restarter : Starting application tk.lsq27.test.TestApplication with URLs [file:/D:/code/spring/test/target/classes/]
如日志所示,应用程序所在的线程不是 main
线程,而是 restartedMain
线程。项目中所做的任何更改,都将导致项目自动重新启动。
修改 TestApplication.java
并保存,触发该文件重新编译,产生日志如下:
2023-03-01 20:15:26.600 INFO 5868 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Restarting due to 1 class path change (0 additions, 1 deletion, 0 modifications)
2023-03-01 20:15:26.600 DEBUG 5868 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Change set: [D:\code\spring\test\target\classes [D:\code\spring\test\target\classes\tk\lsq27\test\TestApplication.class (DELETE)]]
2023-03-01 20:15:26.601 DEBUG 5868 --- [ File Watcher] o.s.boot.devtools.restart.Restarter : Restarting application
2023-03-01 20:15:26.603 DEBUG 5868 --- [ Thread-5] o.s.boot.devtools.restart.Restarter : Stopping application
2023-03-01 20:15:26.686 DEBUG 5868 --- [ Thread-5] o.s.b.d.r.c.RestartClassLoader : Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@d2ccc5d
2023-03-01 20:15:26.687 DEBUG 5868 --- [ Thread-5] o.s.boot.devtools.restart.Restarter : Starting application tk.lsq27.test.TestApplication with URLs [file:/D:/code/spring/test/target/classes/]
2023-03-01 20:15:27.137 INFO 5868 --- [ restartedMain] tk.lsq27.test.TestApplication: Started TestApplication in 0.445 seconds (JVM running for 115.825)
2023-03-01 20:15:29.570 INFO 5868 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Restarting due to 1 class path change (1 addition, 0 deletions, 0 modifications)
2023-03-01 20:15:29.570 DEBUG 5868 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Change set: [D:\code\spring\test\target\classes [D:\code\spring\test\target\classes\tk\lsq27\test\TestApplication.class (ADD)]]
2023-03-01 20:15:29.570 DEBUG 5868 --- [ File Watcher] o.s.boot.devtools.restart.Restarter : Restarting application
2023-03-01 20:15:29.571 DEBUG 5868 --- [ Thread-7] o.s.boot.devtools.restart.Restarter : Stopping application
2023-03-01 20:15:29.634 DEBUG 5868 --- [ Thread-7] o.s.b.d.r.c.RestartClassLoader : Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@600f3336
2023-03-01 20:15:29.634 DEBUG 5868 --- [ Thread-7] o.s.boot.devtools.restart.Restarter : Starting application tk.lsq27.test.TestApplication with URLs [file:/D:/code/spring/test/target/classes/]
一个名为 File Watcher
的线程检测到 target 目录下的 TestApplication.class
被删除,Thread-5
线程将应用停止,创建 RestartClassLoader@d2ccc5d
,将应用启动,耗时 0.445
秒,重启完成后又检测到新增 TestApplication.class
文件,导致 Thread-7
线程将
应用又一次重启,此处我认为是一个设计上的缺陷,修改源代码并保存会导致 class 被删除、重新编译新增 class 两个操作,每次操作都会导致应用重启。
新建一个文件 TestService.java
,同样会导致应用重启,日志如下:
2023-03-01 20:34:44.214 INFO 5868 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Restarting due to 1 class path change (1 addition, 0 deletions, 0 modifications)
2023-03-01 20:34:44.214 DEBUG 5868 --- [ File Watcher] rtingClassPathChangeChangedEventListener : Change set: [D:\code\spring\test\target\classes [D:\code\spring\test\target\classes\tk\lsq27\test\TestService.class (ADD)]]
2023-03-01 20:34:44.214 DEBUG 5868 --- [ File Watcher] o.s.boot.devtools.restart.Restarter : Restarting application
2023-03-01 20:34:44.216 DEBUG 5868 --- [ Thread-11] o.s.boot.devtools.restart.Restarter : Stopping application
2023-03-01 20:34:44.285 DEBUG 5868 --- [ Thread-11] o.s.b.d.r.c.RestartClassLoader : Created RestartClassLoader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@797febdb
2023-03-01 20:34:44.286 DEBUG 5868 --- [ Thread-11] o.s.boot.devtools.restart.Restarter : Starting application tk.lsq27.test.TestApplication with URLs [file:/D:/code/spring/test/target/classes/]
远程调试
spring-boot-devtools 还通过 HTTP 提供开箱即用的远程调试功能。首先,需要将 spring-boot-devtools 打包为应用程序的一部分。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
然后执行以下步骤:
- 将应用打包为JAR
- 使用JRE启动JAR包,增加参数
spring.devtools.remote.secret=password
- 在IDE中启动
org.springframework.boot.devtools.RemoteSpringApplication
,环境变量spring.devtools.remote.secret=password
,程序参数http://localhost:8080
- 修改TestService.java并保存
RemoteSpringApplication
的日志如下:
2023-03-01 21:44:36.308 INFO 5800 --- [ File Watcher] o.s.b.d.r.c.ClassPathChangeUploader : Uploading 1 class path change (0 additions, 1 deletion, 0 modifications)
2023-03-01 21:44:37.516 INFO 5800 --- [pool-1-thread-1] o.s.b.d.r.c.DelayedLiveReloadTrigger : Remote server has changed, triggering LiveReload
2023-03-01 21:44:39.988 INFO 5800 --- [ File Watcher] o.s.b.d.r.c.ClassPathChangeUploader : Uploading 1 class path change (1 addition, 0 deletions, 0 modifications)
2023-03-01 21:44:41.007 INFO 5800 --- [pool-1-thread-1] o.s.b.d.r.c.DelayedLiveReloadTrigger : Remote server has changed, triggering LiveReload
RemoteSpringApplication
监视类路径中的更改,类路径中的任何更改都会导致将更新的资源推送到远程应用程序并触发重新启动。
可以看到,对文件的修改触发两次重启,和上一节的问题一样。
总结
spring-boot-devtools 通过自定义 ClassLoader 实现了应用的快速重启,虽有不足,但不失为应用开发人员的利器。
标签:03,01,spring,boot,---,2023,devtools From: https://www.cnblogs.com/lsq27/p/17170251.html转载请注明出处,使用时须遵循 CC BY-SA 4.0 License 中所述条款。