优化Spring Boot项目启动时间:详解与实践
目录
- 引言
- 了解Spring Boot框架启动机制
- 常见启动瓶颈分析
- 优化策略
- 禁用不必要的自动配置
- 使用@Profile进行开发和生产环境区分
- 精简依赖
- 延迟加载Bean
- 并行初始化Bean
- 缓存数据源连接
- 优化Spring Data JPA
- 使用Spring Boot DevTools
- 通过性能测试工具分析和优化
- 实战示例:一个Spring Boot项目的优化过程
- 结论
- 参考文献
引言
Spring Boot框架由于其自动配置、快速开发的特性得到了开发者的广泛青睐。但是在项目复杂度增加的情况下,启动时间变长成为困扰开发者的一个重要问题。优化启动时间不仅可以提高开发效率,还能提升系统的整体性能。本文将详细介绍如何通过多种方法优化Spring Boot项目的启动时间,并提供具体的实战示例,以帮助读者掌握相关技巧和原理。
了解Spring Boot框架启动机制
在进行任何优化之前,理解Spring Boot的启动流程至关重要。Spring Boot应用主要通过SpringApplication.run
方法启动,该方法会触发以下几个关键步骤:
- 初始化SpringApplication:加载主配置类(即带有
@SpringBootApplication
注解的类)。 - 准备环境:加载配置文件(如application.properties或application.yml),并解析属性。
- 创建ApplicationContext:根据配置生成适当的
ApplicationContext
实例。 - 准备ApplicationContext:初始化上下文环境,配置包扫描、自动配置(Auto-Configuration)等。
- 刷新ApplicationContext:实例化所有单例Bean,触发各种生命周期事件(例如
ContextRefreshedEvent
)。 - 启动完成:运行任何带有
@Bean
标注的方法,执行CommandLineRunner
和ApplicationRunner
。
了解这些步骤后,我们可以针对不同的阶段采取具体的优化措施。
常见启动瓶颈分析
在实际项目中,影响Spring Boot启动速度的主要因素包括:
- Bean生命周期管理:Bean的创建与初始化是一个耗时的重要阶段,尤其是复杂Bean或需要外部资源的Bean。
- 自动配置(Auto-Configuration):Spring Boot的自动配置机制是其核心优势之一,但也带来了一定的启动开销。
- 资源加载:应用程序在启动过程中需要加载大量配置文件、静态资源等。
- 数据源初始化:和数据库交互的Bean通常需要较长时间进行初始化。
- 依赖库加载:项目依赖过多也会导致启动时间大幅增加。
接下来,我们将深入探讨各个阶段的优化策略。
优化策略
禁用不必要的自动配置
Spring Boot提供的许多自动配置功能虽然方便,但不一定都需要用到。我们可以通过排除特定的自动配置类来减少启动时间。
操作步骤:
-
确定不需要的自动配置类。例如,如果不需要Spring Security相关的自动配置,可以如下设置:
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);} }
-
使用
spring.autoconfigure.exclude
属性在配置文件中禁用:spring:autoconfigure:exclude:- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
使用@Profile进行开发和生产环境区分
不同的环境可能需要加载不同的Bean和配置。利用@Profile
注解可以有效地区分开发、测试与生产环境,从而避免加载不必要的Bean。
操作步骤:
-
创建不同环境下的配置类:
@Configuration @Profile("dev") public class DevConfig {// 开发环境配置 }@Configuration @Profile("prod") public class ProdConfig {// 生产环境配置 }
-
启动时指定环境:
# 开发环境 java -jar myapp.jar --spring.profiles.active=dev# 生产环境 java -jar myapp.jar --spring.profiles.active=prod
精简依赖
不必要的依赖项不仅会增加项目的体积,还会显著延长启动时间。定期审查和删除不必要的依赖是一个好习惯。
操作步骤:
- 检查
pom.xml
或build.gradle
文件,删除未使用的依赖。 - 使用
mvn dependency:analyze
或gradle dependencies
命令来分析依赖关系,找出未使用的依赖项。
延迟加载Bean
通过配置懒加载,可以在首次需要使用Bean时再进行初始化,而不是在启动时就实例化所有单例Bean。
操作步骤:
-
在启动类中启用懒加载:
@SpringBootApplication public class MyApplication {public static void main(String[] args) {SpringApplication app = new SpringApplication(MyApplication.class);app.setLazyInitialization(true);app.run(args);} }
-
或者,在需要懒加载的Bean上增加
@Lazy
注解:@Service @Lazy public class MyService {// Service logic }
并行初始化Bean
在多核CPU的机器上,可以利用多线程并行加载Bean以提高启动速度。
操作步骤:
-
在配置文件中启用Bean的并行初始化:
spring:main:allow-bean-definition-overriding: truebean-info-ignore: true
-
自定义线程池并行初始化Bean:
@Configuration public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(7);executor.setMaxPoolSize(42);executor.setQueueCapacity(11);executor.setThreadNamePrefix("MyExecutor-");executor.initialize();return executor;} }
-
在对应的Bean上标注
@Async
注解使其异步初始化:@Service public class MyService {@Asyncpublic void performAsyncTask() {// Executing long-running task} }
缓存数据源连接
如果应用需要频繁地连接数据源,可以通过连接池技术来优化数据源连接,减少初始化时的时间消耗。
操作步骤:
- 使用连接池配置数据源,如HikariCP(Spring Boot 2.x默认连接池):
spring:datasource:type: com.zaxxer.hikari.HikariDataSourceurl: jdbc:mysql://localhost:3306/mydbusername: rootpassword: passwordhikari:minimum-idle: 5maximum-pool-size: 15idle-timeout: 30000pool-name: HikariCPmax-lifetime: 600000connection-timeout: 30000
优化Spring Data JPA
若项目中使用JPA,有以下几个优化策略:
-
禁用DDL自动更新:
spring:jpa:hibernate:ddl-auto: none
-
利用Query DSL生成预编译查询:
@Query("SELECT u FROM User u WHERE u.email = :email") Optional<User> findByEmail(@Param("email") String email);
-
减少不必要的加载、关联:
@Entity public class Order {@ManyToOne(fetch = FetchType.LAZY)private Customer customer; }
使用Spring Boot DevTools
Spring Boot DevTools旨在加快开发过程中的启动和热部署,适合开发环境下加快启动速度。
操作步骤:
-
增加DevTools依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> </dependency>
-
在IDE中启用自动构建功能,这样每次代码变化都会自动重启应用。
通过性能测试工具分析和优化
只有通过定量分析,才能更好地理解优化前后的效果。推荐以下几种性能分析工具:
- VisualVM:可以监控CPU、内存使用情况,设置采样或跟踪来分析应用的性能瓶颈。
- JProfiler:商业工具,功能强大,支持深入分析各种性能问题。
- Java Mission Control (JMC):Oracle提供的免费工具,适用于分析运行时性能,定位性能瓶颈。
操作步骤:
-
使用VisualVM监控Spring Boot项目:
- 启动Spring Boot 应用
- 打开VisualVM,连接应用进程
- 配置采样策略,分析启动过程中CPU和内存的使用
-
JProfiler或JMC类似,可以针对启动阶段设置快照,详细查看类加载、Bean初始化等信息。
实战示例:一个Spring Boot项目的优化过程
为了更直观地展示优化效果,我们以示例项目为例:
初始状态下的项目
- 项目使用Spring Boot 2.5.6,集成了Spring Data JPA和Spring Security。
- 启动类代码:
@SpringBootApplication public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);} }
优化步骤
-
禁用不必要的自动配置:
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);} }
-
使用
@Profile
区分环境:@Configuration @Profile("prod") public class ProdConfig {@Beanpublic DataSource dataSource() {// 配置生产环境的数据源} }@Configuration @Profile("dev") public class DevConfig {@Beanpublic DataSource dataSource() {// 配置开发环境的数据源} }
-
精简依赖,删除未使用的依赖项。
-
启用懒加载:
@SpringBootApplication public class MyApplication {public static void main(String[] args) {SpringApplication app = new SpringApplication(MyApplication.class);app.setLazyInitialization(true);app.run(args);} }
-
并行初始化Bean:
@Configuration public class AsyncConfig implements AsyncConfigurer {@Override public Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(25);executor.setThreadNamePrefix("MyExecutor-"); executor.initialize(); return executor;} }
-
配置数据源连接池:
spring:datasource:type: com.zaxxer.hikari.HikariDataSourceurl: jdbc:mysql://localhost:3306/mydbusername: rootpassword: passwordhikari:minimum-idle: 5maximum-pool-size: 15idle-timeout: 30000pool-name: HikariCPmax-lifetime: 600000connection-timeout: 30000
性能测试与分析
使用VisualVM对优化前后的项目进行分析记录:
- CPU使用:优化后显著减少,主要是因为并行初始化和懒加载减少了不必要的计算量。
- 内存使用:优化后有一定程度降低,主要归功于按需加载和减少未使用的依赖。
- 启动时间:通过JMC记录的启动时间来看,优化后启动时间减少了约30%。
效果总结
- 项目启动时间由初始的20秒降低至14秒,优化效果显著。
- 优化过程中引入了@Lazy和@Async注解,使得代码结构更为灵活。
- 数据源连接池的优化进一步提升了数据交互效率。
结论
优化Spring Boot项目的启动时间是一个系统工程,需要针对具体项目和特定情景采取对应的措施。通过本文的详细解释与示例,相信读者能够更好地理解Spring Boot的启动机制,并应用多种优化策略来提升项目的开发效率和系统性能。
参考文献
- Spring Boot Documentation
- VisualVM官方文档
- JProfiler官方文档
- Java Mission Control官方文档
通过这些方法和工具,开发者可以有效地优化Spring Boot项目的启动时间,提高开发效率和系统性能。希望这篇文章能为您提供实用的参考和帮助。
相关文章:
优化Spring Boot项目启动时间:详解与实践
目录 引言了解Spring Boot框架启动机制常见启动瓶颈分析优化策略 禁用不必要的自动配置使用Profile进行开发和生产环境区分精简依赖延迟加载Bean并行初始化Bean缓存数据源连接优化Spring Data JPA使用Spring Boot DevTools 通过性能测试工具分析和优化实战示例:一个…...
Android如何简单快速实现RecycleView的拖动重排序功能
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点 要实现这个拖动重排序功能,主要是用到了RecycleView的ItemTouchHelper类 首先是定义一个接口 interface ItemTouchHelperAdapter …...
LabVIEW利用旋转编码器脉冲触发数据采集
利用旋转编码器发出的脉冲控制数据采集,可以采用硬件触发方式,以确保每个脉冲都能触发一次数据采集。本文提供了详细的解决方案,包括硬件连接、LabVIEW编程和触发设置,确保数据采集的准确性和实时性。 一、硬件连接 1. 旋转编码…...
Dubbo3 服务原生支持 http 访问,兼具高性能与易用性
作者:刘军 作为一款 rpc 框架,Dubbo 的优势是后端服务的高性能的通信、面向接口的易用性,而它带来的弊端则是 rpc 接口的测试与前端流量接入成本较高,我们需要专门的工具或协议转换才能实现后端服务调用。这个现状在 Dubbo3 中得…...
我在高职教STM32——GPIO入门之蜂鸣器
大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正因如此,才有了借助 CSDN 平台寻求认同感和成就…...
STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建
STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建 文章目录 STM32 Customer BootLoader 刷新项目 (一) STM32CubeMX UART串口通信工程搭建功能与作用典型工作流程 1. 硬件原理图介绍2. STM32 CubeMX工程搭建2.1 创建工程2.2 系统配置2.3 USART串口配…...
如果搜索一定超时,如何用dp来以空间换时间
E - Alphabet Tiles (atcoder.jp) 题目大意:1到k长度的字符串时,在A-Z给定数量下,搭配出多少种不同的字符串 思路 排列组合,会死人的 暴搜:可以解决,但是时间太长 dp:考虑前 i 个字母&…...
MySQL常见的命令
MySQL常见的命令 查看数据库(注意添加分号) show databases;进入到某个库 use 库; 例如:进入test use test;显示表格 show tables;直接展示某个库里面的表 show tables from 库; 例如:展示mysql中的表格 show tabl…...
11 类型泛化
11 类型泛化 1、函数模版1.1 前言1.2 函数模版1.3 隐式推断类型实参1.4 函数模板重载1.5 函数模板类型形参的默认类型(C11标准) 2、类模版2.1 类模板的成员函数延迟实例化2.2 类模板的静态成员2.3 类模板的递归实例化2.4 类模板类型形参缺省值 3、类模板…...
UE4_后期_ben_模糊和锐化滤镜
学习笔记,不喜勿喷,侵权立删,祝愿生活越来越好! 本篇教程主要介绍后期处理的简单模糊和锐化滤镜效果,学习之前首先要回顾下上节课介绍的屏幕扭曲效果: 这是全屏效果,然后又介绍了几种蒙版&#…...
Spring Boot中Excel的导入导出的实现之Apache POI框架使用教程
文章目录 前言一、Apache POI 是什么?二、使用 Apache POI 实现 Excel 的导入和导出① 导入 Excel1. 添加依赖2. 编写导入逻辑3. 在 Controller 中处理上传请求 ② 导出 Excel1. 添加依赖2. 编写导出逻辑3. 在 Controller 中处理导出请求 总结 前言 在 Spring Boot …...
CentOS搭建kubernetes集群详细过程(yum安装方式)
kubernetes集群搭建详细过程(yum安装方式) Kubernetes,也被称为K8s,是一个多功能的容器管理工具,它不仅能够协调和调度容器的部署,而且还能监控容器的健康状况并自动修复常见问题。这个平台是在谷歌十多年…...
Java 面试题:Java 的 Exception 和 Error 有什么区别?
在Java编程中,异常处理是确保程序稳健性和可靠性的重要机制。Java提供了一套完善的异常处理框架,通过捕获和处理异常,开发者可以有效地应对程序运行时可能出现的各种问题。在这一框架中,Exception和Error是两个核心概念࿰…...
在Vue 3中,el-select循环el-option的常见踩坑点,value值绑定对象类型?选中效果不准确?
在Vue 3中,el-select 组件是来自 Element Plus UI 库的一部分。 如果你想要设置默认选中的选项,你可以使用 v-model 来绑定选中的值。如果你想要在某个时刻让某个选项显示为已选中,可以设置对应的值到 v-model 绑定的数据。 <template>…...
Qt实现单例模式:Q_GLOBAL_STATIC和Q_GLOBAL_STATIC_WITH_ARGS
目录 1.引言 2.了解Q_GLOBAL_STATIC 3.了解Q_GLOBAL_STATIC_WITH_ARGS 4.实现原理 4.1.对象的创建 4.2.QGlobalStatic 4.3.宏定义实现 4.4.注意事项 5.总结 1.引言 设计模式之单例模式-CSDN博客 所谓的全局静态对象,大多是在单例类中所见,在之前…...
通过nginx转发后应用偶发502bad gateway
序言 学习了一些东西,如何才是真正自己能用的呢?好像就是看自己的潜意识的反应,例如解决了一个问题,那么下次再碰到类似的问题,能直接下意识的去找到对应的信息,从而解决,而不是和第一次碰到一样…...
linux中如何进行yum源的挂载
linux中如何进行yum源的挂载 1.首先创建目录[rootserver /]# mkdir /rhel92.使用mount命令进行、dev/cdrom/的镜像文件进行挂载[rootserver /]# mount /dev/cdrom /rhel9/ 注意:此时设立的是临时命令。重启后则失效,若想在下次开启后仍然挂载&a…...
ffmpeg的部署踩坑及简单使用方式
ffmpeg的使用方式有以下几种: 使用原生安装包 直接在ffmpeg官网上下载安装该软件,加入到环境变量中就可以使用了 优点:简单,灵活,代码中也不用添加其他第三方的包 缺点:需要手动安装ffmpeg,这点比较麻烦 部署-windows 在windows环境下,有时就算加入到了环境变量,…...
misc刷题记录2[陇剑杯 2021]
[陇剑杯 2021]webshell (1)单位网站被黑客挂马,请您从流量中分析出webshell,进行回答: 黑客登录系统使用的密码是_____________。得到的flag请使用NSSCTF{}格式提交。 这里我的思路是,既然要选择的时间段是黑客登录网站以后&…...
AI发展面临的问题? —— AI对创造的重新定义
一、AI的问题描述 AI与数据安全问题:随着AI技术的发展和应用,数据安全问题日益突出。AI模型训练依赖于大量数据,而这些数据中可能包含个人隐私、商业秘密等敏感信息。如果数据在采集、存储、使用过程中处理不当,可能导致数据泄露或…...
k8s学习--OpenKruise详细解释以及原地升级及全链路灰度发布方案
文章目录 OpenKruise简介OpenKruise来源OpenKruise是什么?核心组件有什么?有什么特性和优势?适用于什么场景? 什么是OpenKruise的原地升级原地升级的关键特性使用原地升级的组件原地升级的工作原理 应用环境一、OpenKruise部署1.安…...
上海亚商投顾:沪指缩量调整 PCB概念股持续爆发
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 大小指数昨日走势分化,沪指全天震荡调整,创业板指午后涨超1%。消费电子板块全天强势&a…...
QT属性系统,简单属性功能快速实现 QT属性的简单理解 属性学习如此简单 一文就能读懂QT属性 QT属性最简单的学习
4.4 属性系统 Qt 元对象系统最主要的功能是实现信号和槽机制,当然也有其他功能,就是支持属性系统。有些高级语言通过编译器的 __property 或者 [property] 等关键字实现属性系统,用于提供对成员变量的访问权限,Qt 则通过自己的元对…...
【IEEE出版丨EI检索】2024新型电力系统与电力电子国际会议(NPSPE 2024)
2024新型电力系统与电力电子国际会议(NPSPE 2024)将于8月16日至18日在中国大连举行,本届大会致力于为相关领域的专家和学者提供一个探讨行业热点问题,促进科技进步,增加科研合作的平台。本届大会涵盖新型电力系统和电力…...
【Netty】nio阻塞非阻塞Selector
阻塞VS非阻塞 阻塞 阻塞模式下,相关方法都会导致线程暂停。 ServerSocketChannel.accept() 会在没有建立连接的时候让线程暂停 SocketChannel.read()会在没有数据的时候让线程暂停。 阻塞的表现就是线程暂停了,暂停期间不会占用CPU,但线程…...
ES 操作
1、删除索引的所有记录 curl -X POST "localhost:9200/<index-name>/_delete_by_query" -H Content-Type: application/json -d {"query": {"match_all": {}} }POST /content_erp_nlp_help/_delete_by_query { "query": { &quo…...
uniapp如何实现跳转
在 UniApp 中,页面跳转主要可以通过两种方式实现:使用 <navigator> 组件和调用 UniApp 提供的导航 API。以下是这两种方式的详细说明: 1. 使用 <navigator> 组件 <navigator> 组件允许你在页面上创建一个可点击的元素&am…...
Stable-Diffusion-WebUI 常用提示词插件
SixGod提示词插件 SixGod提示词插件可以帮助用户快速生成逼真、有创意的图像。其中包含,清空正向提示词”和“清空负向提示词、提示词起手式包含人物、服饰、人物发型等各个维度的提示词、一键清除正面提示词与负面提示词、随机灵感关键词、提示词分类组合随机、动…...
单片机 PWM输入捕获【学习记录】
前言 学习是永无止境的,就算之前学过的东西再次学习一遍也能狗学习到很多东西,输入捕获很早之前就用过了,但是仅仅是照搬例程没有去进行理解。温故而知新! 定时器 定时器简介 定时器的分类 高级定时器 通用定时器 基本定时器…...
3.1、前端异步编程(超详细手写实现Promise;实现all、race、allSettled、any;async/await的使用)
前端异步编程规范 Promise介绍手写Promise(resolve,reject)手写Promise(then)Promise相关 API实现allraceallSettledany async/await和Promise的关系async/await的使用 Promise介绍 Promise是一个类,可以翻…...
网页制作网站创建/浙江网站推广运营
Bessel函数介绍贝塞尔函数(Bessel functions)是数学上的一类特殊函数的总称。一般贝塞尔函数是下列常微分方程(一般称为贝塞尔方程)的标准解函数y(x):这类方程的解是无法用初等函数系统地表示的。贝塞尔函数的具体形式随上述方程中任意实数α变化而变化(相应地&…...
wordpress会员可见/域名服务器ip查询网站
本节内容只有通过例题来记录效果才是最好的,请看下面内容! 递归实现二分法 经典二分查找问题:LintCode 炼码 描述**:**在一个排序数组中找一个数,返回该数出现的任意位置,如果不存在,返回 -1。 输入&…...
做商业广告有什么网站好推销的/快速收录工具
原文(我的博客):贝叶斯估计、最大似然估计、最大后验估计三者的区别 更多机器学习深度学习资源 实例分析 即使学过机器学习的人,对机器学习中的 MLE(极大似然估计)、MAP(最大后验估计)以及贝叶斯估计(Bayesian) 仍有可能一知半解。对于一个基础模型,通常…...
网上购物网站建设的实训报告/舆情信息
1.正则表达式回溯问题解析转载于:https://www.cnblogs.com/MagicalFool/p/10077399.html...
网站建设 汇卓/淘宝推广怎么做
转载https://blog.csdn.net/gesanghua601/article/details/85131156 最近经常利用wireshark抓包,查看数据包的数据,遇到一二问题总结下,也分享给遇到同样问题的小伙伴儿~~ 抓包rtp难以直观看到裸码流格式数据,进而难以判断码流类…...
长沙公司网站的建设/百度网盘官方
维特比算法看一下维基百科的解释,维特比算法(Viterbi algorithm)是一种动态规划算法。它用于寻找最有可能产生观测事件序列的维特比路径——隐含状态序列,特别是在马尔可夫信息源上下文和隐马尔可夫模型中。通俗易懂的解释知乎有很…...