DevTools 重启功能介绍
spring-boot-devtools
会在源码路径src/main
上的文件发生更改时自动重启SpringApplication
。这样当我们改变一个类的时候,不需要点击编译器的重启按钮。但是重启的粒度其实还是比较大的,是重启整个Spring容器。 尤其是我们的应用内容过多或者包含着web容器的时候。当然和这个工具有类似功能的还有Jrebel,它使用的技术是重载,粒度小,但是收费。不在我们今天的讨论范围之内。
重启和重载的区别
The restart technology provided by Spring Boot works by using two classloaders. Classes that do not change (for example, those from third-party jars) are loaded into a base classloader. Classes that you are actively developing are loaded into a restart classloader.
When the application is restarted, the restart classloader is thrown away and a new one is created. This approach means that application restarts are typically much faster than “cold starts”, since the base classloader is already available and populated.
If you find that restarts are not quick enough for your applications or you encounter classloading issues, you could consider reloading technologies such as JRebel from ZeroTurnaround. These work by rewriting classes as they are loaded to make them more amenable to reloading.
首先重启的粒度是比较大的,每次启动,Spring容器会重新启动。而重载的粒度是一个类,把类通过类加载器重新加载到JVM中。
原理分析
流程总览
首先我们看一下, SpringBoot 从监听文件变化,到重新启动的序列图,一句话解释就是:首先有一个检测文件变化线程,如果检测到文件(泛指class文件)变化了,就重启服务器。
源码分析
SpringBoot
的 起点都是从AutoConfiguration
开始的,当然DevTools
也不例外
文件变化触发机制的实现
那么我们首先来看一下这个配置
@Configuration
@ConditionalOnProperty(prefix = "spring.devtools.restart", name = "enabled", matchIfMissing = true)
static class RestartConfiguration
implements ApplicationListener<ClassPathChangedEvent> {
private final DevToolsProperties properties;
RestartConfiguration(DevToolsProperties properties) {
this.properties = properties;
}
@Override
public void onApplicationEvent(ClassPathChangedEvent event) {
if (event.isRestartRequired()) {
Restarter.getInstance().restart(
new FileWatchingFailureHandler(fileSystemWatcherFactory()));
}
}
@Bean
@ConditionalOnMissingBean
public ClassPathFileSystemWatcher classPathFileSystemWatcher() {
URL[] urls = Restarter.getInstance(