SpringBoot 启动慢?那是因为你不知道它
前言
在 2021 年这个小学作文中的未来年份,没有想象中的汽车满天飞,也没有实现机器人满地跑。但牛逼的是我们都有一个共识: 知乎达到了人均 “谢邀~ 人在美国刚下飞机”的生活水平,虎扑的人均收入也在 30W+ ,还有就是程序员都人均精通 SpringBoot ,哪怕和算法聊技术一言不合就满嘴 SpringCould 分布式、微服务,然而实际操作可能是 分步试 、伪服务 ... 你一个小小系统开这么多应用启动不难受?(不难受因为可以装 13) SpringBoot 这启动速度也确实令人捉急,每个应用 5 分钟改个小功能,编码五分钟部署俩小时。 so 如何更加优雅快速的 启动 SpringBoot 应用 (满足装 13 的欲望) 呢?

其实我们都比较清楚大部分的启动时间是由于 Spring 需要加载各种 Bean 导致启动速度下降的,那么对于那些不是特别重要的 Bean 我们是不是可以让他再起一个线程做 Bean 初始化,不阻塞主线程启动,这样启动速度不就起来了么,说干就干!
那你肯定会问,我们咋判断一个 Bean 加载时间长短,找出那些 拉跨的Bean 呢?内心一阵嘲讽,嘴角泛出一阵冷笑后 不慌不忙的道来:“这对于精通 Spring 框架的我来说不是小菜一碟么 ”。我掐指一算,就知道是哪几个 Bean 拉跨。

统计 Bean 初始化时间
简单做法就是通过 BeanPostProcessor ,祭出这个神器就能干倒一半的 LSP,很多使用 Spring 的 LSP 其实都不太知道这个玩意,那他到底是个什么玩意呢?简单来讲就是 Spring 初始化 Bean 的钩子函数。 Bean 是否加载,加载的是哪个 Bean 以及修改 Bean 的相关属性都可以通过这个钩子函数搞定。这就是一个活生生的 Spring 后门,学会了他 Spring 框架任你摆布。
后面我会专门开一篇文章去讲解 BeanPostProcessor 如何帮你加载 Bean,以及如何利用这个后门搞事情。

所以我们现在讲讲如何用 BeanPostProcessor 统计 Bean 的初始化时间。不多 BB 直接上代码:

我们编写了 BeanInitCostTimeBeanPostProcessor 继承了 BeanPostProcessor 实现了 postProcessBeforeInitialization 和 postProcessAfterInitialization 分别代表了 Bean 初始化之前和之后,简单记录了 Bean 初始化开始时间,然后用结束时间减去开始时间就得到了具体的初始化时间。
我专门在 Spring 容器中放了一个加载时间很长的测试 Bean ,代码如下

效果如下:

异步 Bean 实操
异步 Bean 异步 Bean ,首先这个 Bean 需要是个异步的,那如何将一个 Bean 包装成异步的呢?首先异步 Bean 肯定需要继承原来的 Bean 需要保证是同一种类型的,然后重写他的 init 方法。代码操作如下:

但是这么写并不是很优雅,假如我们还需要在初始化 Bean 的时候做一些其他操作,直接继承是不方便的。所以必须祭出 Spring 中的另外一个组件了,工厂 Bean,学名 FactoryBean 这个要和另外一个叫做 BeanFactory 的大佬区分开。 工厂 Bean 顾名思义就是这个玩意也是一个 Bean 只是他的主要职责是作为工厂,通常用于生成特定类型的 Bean ,那么我们就有一个骚操作了,让这个工厂生产的 Bean 就是它自己,而且中间还能定义很多额外的逻辑,不多 BB 上代码

然后通过异步 Bean 去加载我们看看前后的差别

优化之前:

优化之后:

可以看到优化后 1.4s 应用就启动完成了,而且耗时的 Bean 可以让他慢慢加载,在应用启动完成后这个 Bean 才完全被加载。
唠叨
最近有点忙成狗,从四月就断更到现在了,今天抽个周末的时候终于写完了。
不过最近看了好几本书,也准备抽点时间写写读后感了,非常推荐大家看看 《零秒思考》 ,同时写点个人的小思考: 一旦适应了用语言表达脑海中的意向和感觉,渐渐地就不会为如何表达自己的心情和想法而苦恼,流畅清晰的表达能够更快的与对方沟通让对方心领神会。表达不善往往便会产生一种想也是白想的放弃心理,由此甚至连思考本身也放弃了,不思考人就不会成长,不经历思考解决手头的事情人就会失去干劲变得无聊。
SpringBoot 启动慢?那是因为你不知道它的更多相关文章
- springboot启动太慢优化
需求缘起:有人在[springboot]微信公众号问:springboot启动慢的问题何时有个分享就好了,谢谢.粉丝的问题还是要认真的回答的. 我们先看看本节的大纲: (1)组件自动扫描带来的问题(@ ...
- SpringBoot启动流程分析(六):IoC容器依赖注入
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- SpringBoot启动流程分析(三):SpringApplication的run方法之prepareContext()方法
SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...
- springboot启动后自动退出
有时新建的springboot启动后自动退出运行,如图所示: 此种情况大都数是因为pom文件加入了tomcat的依赖,与springboot内嵌的tomcat冲突导致,所以只需将pom文件中的tomc ...
- Springboot启动一直卡在{dataSource-1} inited
Springboot启动一直卡在{dataSource-1} inited 错误原因: 暂时未知,猜测是因为设置端点的问题 解决办法: 去除所有断点: 然后再次启动就好了. 如果还有错: 那么重新导入 ...
- 【转载】springboot启动报错(Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWe)
SpringBoot启动时的异常信息如下: 1 "C:\Program Files\Java\jdk1.8.0_161\bin\java" ......... com.fangxi ...
- springboot启动过程
使用了很长时间的springboot了,一直都知道它简单易用,简化了框架的搭建过程,但是还是不知道它是如何启动的,今天就跟着springboot的源码,去探探这其中的奥妙 以下是spring应用的启动 ...
- SpringBoot启动使用elasticsearch启动异常:Received message from unsupported version:[2.0.0] minimal compatible
SpringBoot启动使用elasticsearch启动异常:Received message from unsupported version:[2.0.0] minimal compatible ...
- 微服务中springboot启动问题
log4j:WARN No appenders could be found for logger (org.springframework.web.context.support.StandardS ...
- (四)SpringBoot启动过程的分析-预处理ApplicationContext
-- 以下内容均基于2.1.8.RELEASE版本 紧接着上一篇(三)SpringBoot启动过程的分析-创建应用程序上下文,本文将分析上下文创建完毕之后的下一步操作:预处理上下文容器. 预处理上下文 ...
随机推荐
- 微信小程序:删除时提示是否删除
代码如下: wx.showModal({ title: '提示', content: '确定要删除吗?', success: function (sm) { if (sm.confirm) { // ...
- 微信小程序:给data中对象中的属性设置值与给data中的属性或对象或数组设置值的区别
一.给data中的属性或对象或数组设置值,属性名不需要加引号 this.setData({ material: param, // 这里material为对象 } this.setData({ d ...
- EFCodeFirst属性映射约定
EFCodeFirst属性映射约定 EFCodeFirst 属性映射约定 CodeFirst与数据表之间得映射方式又两种:Data Annotation和Fluent API 默认约定: 表名为类名的 ...
- 安鸾渗透实战平台-PHP代码练习
0x00 前言 --工欲善其事,必先利其器 0x01 代码理解 (1)linux命令 pwd 查看当前工作目录的完整路径 cd / 切换到根目录 ls / 查看根目录下的所有目录和文件 cat /[f ...
- go 在crontab里面运行报错 解决方案
问题背景 你高高兴兴的写好了一个go脚本,放到你的服务器上,打算定期运行这个脚本,你打开crontab -e, 然后输入: */1 * * * * go run /root/test/main.go ...
- 剑指 Offer 40. 最小的k个数 + 优先队列 + 堆 + 快速排序
剑指 Offer 40. 最小的k个数 Offer_40 题目描述 解法一:排序后取前k个数 /** * 题目描述:输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7. ...
- 关于KMP算法中,获取next数组算法的理解
参考:KMP入门级别算法详解--终于解决了(next数组详解) https://blog.csdn.net/lee18254290736/article/details/77278769 在这里讨论的 ...
- 记离线部署docker,以及docker下部署zabbix
一.离线安装docker 下载地址:https://download.docker.com/linux/static/stable/x86_64/ 上传软件并解压 [root@localhost op ...
- Ubuntu小配置
Ubuntu 拍摄快照 在虚拟机安装好.配置号后各拍摄一次快照,并存储. 可在虚拟机出错后回滚 Root用户 Ubuntu默认不能以 Root用户身份直接登录 因此,正常操作时在需要调用 root权限 ...
- Idea 报错 xxxx too long
问题:写单元测试,debug时,报错如下图 解决方法1: 在项目/.idea/workspace.xml文件中添加一行代码如下 <component name="PropertiesC ...