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启动过程的分析-创建应用程序上下文,本文将分析上下文创建完毕之后的下一步操作:预处理上下文容器. 预处理上下文 ...
随机推荐
- Vue3.0+Electron聊天室|electron跨平台仿QQ客户端|vue3.x聊天应用
基于vue3+electron11跨端仿制QQ桌面应用实战Vue3ElectronQchat. 使用vue3+electron+vuex4+ant-design-vue+v3scroll+v3laye ...
- Python函数注解
目录 函数注解概述 实际应用 inspect模块 业务代码 总结 以下内容基于Python 3x 涉及的知识前提: 建议理解Python装饰器后学习此内容 函数注解概述 函数注解可以针对函数的参数.返 ...
- ng-class动态类几种用法
方法1.逻辑在后面的中括号里面 ng-class="{true : 'checker disabled',false : 'checker' }[selectAllButton]" ...
- c++指针数组与二维数组的最大区别
下面随笔是关于指针数组说明及与二维数组的最大区别. 指针数组 数组的元素是指针型 例 利用指针数组存放矩阵 1 #include 2 using namespace std; 3 int main() ...
- [数据结构与算法-13]ST表
ST表 主要用来快速查询静态数据区间最大值 思路 数组\(A[i][j]\)存储数列\(\{a_i\}\)中区间\(i \in [i, i+2^j)\)的最大值 查询时只需要查询\(max\{A[i] ...
- 深入浅出新一代跨平台抓包&调式利器Fiddler Everywhere
什么是Fiddler Everywhere? Fiddler Everywhere is a web debugging proxy for macOS, Windows, and Linux. Ca ...
- CVE-2016-10033 WordPress <= 4.6 命令执行漏洞
漏洞参考 https://www.jianshu.com/p/85ac4af9f947 漏洞信息 这个锅还是要PHPMailer背(CVE-2016-10033,WordPress 使用 PHPMai ...
- go-优雅地关机或重启
目录 优雅地关机或重启 优雅地关机 什么是优雅关机? 如何实现优雅关机? 优雅地重启 总结 优雅地关机或重启 我们编写的Web项目部署之后,经常会因为需要进行配置变更或功能迭代而重启服务,单纯的kil ...
- Apache配置 4.访问日志
(1)介绍 访问日志作用很大,不仅可以记录网站的访问情况,还可以在网站有异常发生时帮助我们定位问题. (2)配置 # vi /usr/local/apache2.4/conf/extra/httpd- ...
- python模块的打包和安装
假设需要打包的模块文件名是mm.py,代码如下: a = 2 在mm.py文件的同目录下新建一个setup.py文件,代码如下: from distutils.core import setup se ...