在本教程中,我们将介绍有助于减少SpringBoot启动时间的不同配置和设置:首先,我们将讨论Spring特定的配置。其次,我们将介绍Java虚拟机选项。最后,我们将介绍如何利用GraalVM和本机镜像编译来进一步缩短启动时间。 延迟初始化 SpringFramework支持延迟初始化。延迟初始化意味着Spring不会在启动时创建所有bean。此外,在需要该bean之前,Spring不会注入任何依赖项。从SpringBoot2。2版开始。可以使用application。properties启用延迟初始化: spring。main。lazyinitializationtrue 根据我们代码库的大小情况,延迟初始化甚至会导致很大的启动时间减少。这种减少取决于我们应用程序的依赖关系图。 此外,延迟初始化在使用DevTools热重启功能的开发过程中也有好处。使用延迟初始化增加重启次数将使JVM能够更好地优化代码。 但是,延迟初始化有一些缺点。最显着的缺点是应用程序会较慢地处理第一个请求。因为Spring需要时间来初始化所需的bean,另一个缺点是我们可能会在启动时遗漏一些错误。这可能会在运行时导致ClassNotFoundException。 排除不必要的自动配置 SpringBoot总是喜欢约定而不是配置。Spring可能会初始化我们的应用程序不需要的bean。我们可以使用启动日志检查所有自动配置的bean。在application。properties中的org。springframework。boot。autoconfigure上将日志记录级别设置为DEBUG: logging。level。org。springframework。boot。autoconfigureDEBUG 在日志中,我们将看到专用于自动配置的新行,然后根据这些输出,我们可以排除这些应用程序配置。 为了排除部分配置,我们使用EnableAutoConfiguration注解:EnableAutoConfiguration(exclude{JacksonAutoConfiguration。bclassb,JvmMetricsAutoConfiguration。bclassb,LogbackMetricsAutoConfiguration。bclassb,MetricsAutoConfiguration。bclassb}) 如果我们排除JacksonJSON库和一些我们不使用的指标配置,我们可以在启动时节省一些时间。 切换到Undertow SpringBoot带有一个嵌入式servlet容器。默认情况下,我们得到Tomcat。虽然Tomcat在大多数情况下已经足够好,但其他servlet容器的性能可能更高。在测试中,来自JBoss的Undertow的性能优于Tomcat或Jetty。它需要更少的内存并具有更好的平均响应时间。要切换到Undertow,我们需要更改pom。xml:dependencygroupIdorg。springframework。bootgroupIdspringbootstarterwebartifactIdexclusionsexclusiongroupIdorg。springframework。bootgroupIdspringbootstartertomcatartifactIdexclusionexclusionsdependencydependencygroupIdorg。springframework。bootgroupIdspringbootstarterundertowartifactIddependency 生成索引 Spring类路径扫描是快速操作。当我们拥有大型代码库时,我们可以通过创建静态索引来缩短启动时间。我们需要给springcontextindexer添加一个依赖来生成索引。Spring不需要任何额外的配置。在编译时,Spring将在METAINFspring。components中创建一个附加文件。Spring会在启动时自动使用它:dependencygroupIdorg。springframeworkgroupIdspringcontextindexerartifactIdversion{spring。version}versionoptionalbtrueboptionaldependency 搜索多个位置 application。properties(或。yml)文件有几个有效的位置。最常见的是在类路径根目录或与jar文件相同的文件夹中。我们可以通过使用spring。config。location参数设置显式路径来避免搜索多个位置,并在搜索时节省几毫秒:javajar。argetspringStartupApp。jarspring。config。locationclasspath:application。properties 最后,SpringBoot提供了一些MBean来使用JMX监控我们的应用程序。完全关闭JMX并避免创建这些bean的成本: spring。jmx。enabledfalse JVM的Verify调整 此标志设置字节码验证器模式。字节码验证提供类的格式是否正确以及是否在JVM规范约束内。我们在启动期间在JVM上设置了这个标志。 Verify标志有几个选项:Xverify是默认值并启用对所有非引导加载程序类的验证。Xverify:all启用对所有类的验证。此设置将对初创公司产生显着的负面性能影响。Xverify:none(或Xnoverify)。此选项将完全禁用验证程序并将显着减少启动时间。 我们可以在启动时传递这个标志:javajarnoverify。argetspringStartupApp。jar 我们将收到来自JVM的警告,指出该选项已被弃用。但是启动时间减少了。 这个标志带来了重要的权衡。我们的应用程序可能会在运行时因我们可以更早捕获的错误而中断。这是该选项在Java13中被标记为已弃用的原因之一。因此它将在未来版本中删除。 JVM分层编译标志 Java7引入了分层编译。HotSpot编译器将对代码使用不同级别的编译。 众所周知,Java代码首先被解释为字节码。接下来,字节码被编译成机器码。这种转换发生在方法级别。C1编译器在一定数量的调用后编译一个方法。运行更多次之后,C2编译器会编译它,从而进一步提高性能。 使用XX:TieredCompilation标志,我们可以禁用中间编译层。这意味着我们的方法将使用C2编译器进行解释或编译,以实现最大程度的优化。这不会导致启动速度下降。我们需要的是禁用C2编译。我们可以使用XX:TieredStopAtLevel1选项来做到这一点。结合noverify标志,这可以减少启动时间。不幸的是,这会在后期减慢JIT编译器的速度。 SpringNative 本机映像镜像(Image)是使用提前编译器编译并打包成可执行文件的Java代码。它不需要Java来运行。由于没有JVM开销,因此生成的程序速度更快,对内存的依赖更少。该GraalVM项目介绍本机映像和所需的构建工具。 SpringNative是一个实验性模块,支持使用GraalVM原生镜像编译器对Spring应用程序进行原生编译。提前编译器在构建期间执行多项任务以减少启动时间(静态分析、删除未使用的代码、创建固定类路径等)。原生镜像仍然有一些限制:它不支持所有Java功能反射需要特殊的配置懒加载类不可用Windows兼容性是一个问题。 要将应用程序编译为原生映像,我们需要将springaot和springaotmavenplugin依赖项添加到pom。xml。Maven将在目标文件夹中的package命令上创建本机映像。