20.2、自动重启
使用 spring-boot-devtools
的应用在 classpath 下的文件发生更改时会自动重启。这对于使用 IDE 工作而言可能是一个非常棒的功能,因为它为代码变更提供了非常块的反馈环。默认情况下,将监视 classpath 指向的所有文件夹。请注意,某些资源(如静态资源和视图模板)不需要重启应用。
触发重启
当 DevTools 监视 classpath 资源时,触发重启的唯一方式是更新 classpath。使 classpath 更新的方式取决于您使用的 IDE。在 Eclipse 中,保存修改的文件将更新 classpath,从而触发重启。在 IntelliJ IDEA 中,构建项目(Build -> Make Project
) 将产生相同的效果。
注意
只要 forking 被开启,您可以使用受支持的构建工具(如 Maven 或 Gradle)来启用应用,因为 DevTools 需要隔离应用类加载器才能正常运行。默认情况下,当在 classpath 下检测到 DevTools 时,Gradle 和 Maven 会这么做。
提示
自动重启功能与 LiveReload(实时重载)一起使用效果更棒。阅读 LiveReload 章节以获取更多信息。如果您使用 JRebel,自动重启将会被禁用,以支持动态类重载,但其他 devtools 功能(如 LiveReload 和 property 覆盖)仍然可以使用。
注意
DevTools 依赖于应用上下文的关闭钩子,以在重启期间关闭自己。如果禁用了关闭钩子(
SpringApplication.setRegisterShutdownHook(false)
),它将不能正常工作。
注意
当 classpath 下的内容发生更改,决定是否触发重启时,DevTools 会自动忽略名为
spring-boot
、spring-boot-devtools
、spring-boot-autoconfigure
、spring-boot-actuator
和spring-boot-starter
的项目。
注意
DevTools 需要自定义
ApplicationContext
使用到的ResourceLoader
。如果您的应用已经提供了一个,它将被包装起来,因为不支持在ApplicationContext
上直接覆盖getResource
方法。
重启(Restart)与重载(Reload)
Spring Boot 通过使用两个类加载器来提供了重启技术。不改变的类(例如,第三方 jar)被加载到 base 类加载器中。经常处于开发状态的类被加载到 restart 类加载器中。当应用重启时,restart 类加载器将被丢弃,并重新创建一个新的。这种方式意味着应用重启比冷启动要快得多,因为省去 base 类加载器的处理步骤,并且可以直接使用。
如果您觉得重启还不够快,或者遇到类加载问题,您可以考虑如 ZeroTurnaround 的 JRebel 等工具。他们是通过在加载类时重写类来加快重新加载。
20.2.1、条件评估变更日志
默认情况下,每次应用重启时,都会记录显示条件评估增量的报告。该报告展示了在您进行更改(如添加或删除 bean 以及设置配置属性)时对应用自动配置所作出的更改。
要禁用报告的日志记录,请设置以下属性:
spring.devtools.restart.log-condition-evaluation-delta=false
20.2.2、排除资源
某些资源在更改时不一定需要触发重启。例如,Thymeleaf 模板可以实时编辑。默认情况下,更改 /META-INF/maven
、/META-INF/resources
、/resources
、/static
、/public
或者 /templates
不会触发重启,但会触发 LiveReload。如果您想自定义排除项,可以使用 spring.devtools.restart.exclude
属性。例如,仅排除 /static
和 /public
,您可以设置以下内容:
spring.devtools.restart.exclude=static/**,public/**
提示
如果要保留这些默认值并添加其他排除项 ,请改用
spring.devtools.restart.additional-exclude
属性。
20.2.3、监视附加路径
如果您想在对不在 classpath 下的文件进行修改时重启或重载应用,请使用 spring.devtools.restart.additional-paths
属性来配置监视其他路径的更改情况。您可以使用上述的 spring.devtools.restart.exclude
属性来控制附加路径下的文件被修改时是否触发重启或只是 LiveReload。
20.2.4、禁用重启
您如果不想使用重启功能,可以使用 spring.devtools.restart.enabled
属性来禁用它。一般情况下,您可以在 application.properties
中设置此属性(重启类加载器仍将被初始化,但不会监视文件更改)。
如果您需要完全禁用重启支持(例如,可能它不适用于某些类库),您需要在调用 SpringApplication.run(...)
之前将 System 属性 spring.devtools.restart.enabled System
设置为 false
。例如:
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}
20.2.5、使用触发文件
如果您使用 IDE 进行开发,并且时时刻刻在编译更改的文件,或许您只是希望在特定的时间内触发重启。为此,您可以使用触发文件,这是一个特殊文件,您想要触发重启检查时,必须修改它。更改文件只会触发检查,只有在 Devtools 检查到它需要做某些操作时才会触发重启,可以手动更新触发文件,也可以通过 IDE 插件更新。
要使用触发文件,请设置 spring.devtools.restart.trigger-file
属性指向触发文件的路径。
提示
您也许想将
spring.devtools.restart.trigger-file
设置成一个全局配置,以使得所有的项目都能应用此方式。
20.2.6、自定义重启类加载器
正如之前的重启和重载部分所述,重启功能是通过使用两个类加载器来实现的。对于大多数应用而言,这种方式很好,然而,有时可能会导致类加载出现问题。
默认情况下,IDE 中任何打开的项目将使用 restart 类加载器加载,任何常规的 .jar
文件将使用 base 类加载器加载。您如果开发的是多模块项目,而不是每一个模块都导入到 IDE 中,则可能需要自定义。为此,您可以创建一个 META-INF/spring-devtools.properties
文件。
spring-devtools.properties
文件可以包含以 restart.exclude.
和 restart.include.
为前缀的属性。include
元素是加载到 restart 类加载器的项,exclude
元素是加载到 base 类加载器的项。属性值是一个应用到 classpath 的正则表达式。例如:
restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar
注意
所有属性键名必须是唯一的。只要有一个属性以
restart.include.
或restart.exclude.
开头,它将会被考虑。
提示
classpath 下的所有
META-INF/spring-devtools.properties
文件将被加载,您可以将它们打包进工程或者类库中为项目所用。
20.2.7、已知限制
重新启动功能对使用标准 ObjectInputStream
反序列化的对象无效。您如果需要反序列化数据,可能需要使用 Spring 的 ConfigurableObjectInputStream
配合 Thread.currentThread().getContextClassLoader()
。
遗憾的是,一些第三方类库在没有考虑上下文类加载器的情况下使用了反序列化。您如果遇到此问题,需要向原作者提交修复请求。