务实优化:将本地单元测试Spring启动速度从1分半优化到16秒,全流程详解
-
1
-
背后的故事
某个平凡熟悉的早上,传来测试同学的一阵哀嚎:那个谁!你提测的代码连运行都不能运行,苦涩。
我默不作声,因为主项目还没有完全服务化,主项目的整体war
包太大,加上从来没有讲究过,开发同学跑一个测试用例,往往启动Spring
就要花一分半钟,哪里有心情按规范跑单测呢?同问了几个开发同学也都有同样的痛点,感觉解决单测环境刻不容缓,古人云:工欲善其事,必先利其器,对吧?
-
2
-
来了,老弟
将日志级别调至Debug级别
没错,这是我们需要做的第一步最重要的步骤,开启单测,把日志打到一个文件里,从头撸到尾,究竟你这加载的一分半钟究竟干嘛了~
一些Spring配置初始化
根据ComponentScan扫路径的Class类,加入待注入候选列表
根据Mapper扫路径的Class类,加入待注入候选列表
对扫出来的Mapper创建MapperFactoryBean
创建注入@Configuration里@Bean注解的Bean的BeanDefinitions
预加载一些Bean
一些组件例如,PostProcessor、Advisor初始化
一些中间件例如数据库、缓存、消息队列加载
扫描的Bean的初始化,依赖注入。。
Bean的PostConstruct开始跑
....//可能不是很全,列举了其中一部分
默默的看了眼日志,20M,妈耶,引了一个ApplicationContextAware
看了一下BeanFactory
,好吧,加载了1500个Bean
,Spring
默认的Ioc容器会把所有的Bean在启动时,都加载成功,首先想到的措施是让Bean懒加载,按需加载,不用的就不加载嘛,很简单!
坑来了:如何对Bean进行懒加载?
简单的网上冲浪了一下,我们需要将
注解法:@ComponentScan(value = "com.evanyz",lazyInit = true) //将这个配置设为true
//xml里是beans里有一个default-lazy-init标签
可是设置成功之后,完全不生效,还是1500个,尝试许久,还是没生效,感觉很懵逼,甚至都有点开始怀疑Spring
了。
排查许久后,突然发现为什么Debug
的时候,会报一些该Bean重复已存在忽略的错,突然灵光一现。MD,我们项目里写代码根本不讲究,每一个子项目里,例如common
、biz
都含有Spring
的初始化文件。
也就是说,从这个初始化配置之后,继续扫其他的配置文件,还是会继续加载,导致之前的配置失效。。
举例:
我在test的初始化类里配置了 @ComponentScan(value = "com.evanyz",lazyInit = true) ,
当他扫到biz子项目的时候,发现另外一个Spring的配置文件是
@ComponentScan(value = "com.evanyz")
这时候懒加载会被覆盖掉,就不生效了。。
这时候想到的办法就是 在test配置里加上一些操作,解释见注解
@ComponentScan(
//扫包
value = {com.evanyz"},
//排除一些Bean
excludeFilters = {
//做点小优化,让他把一些在跑单测时的扩展点不要注入
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = {
SmsServicePostProcessor.class, CatUrlPostProcessor.class,
}),
//按政策排除,把一些其他项目里的Spring配置去掉
@ComponentScan.Filter(type = FilterType.REGEX, pattern = {
"com\\.evanyz\\.test\\..*",
"com\\.evanyz\\.biz\\.springconfig..*",
"com\\.evanyz\\.common\\.springconfig..*",
"com\\.evanyz\\.common\\.cat..*"
}),
//最后清掉了发现,还是有一些配置被加载了
//一不做二不休,我全干掉,搞白名单还不行吗?哭哭
@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {
ComponentScan.class, Configuration.class, ImportResource.class
}),
}, lazyInit = true
)
经过以上的一顿操作,Spring终于懒加载了,直观的看一下之后的Debug
,瘦身了3倍,爽!
继续优化,Mock一些毒瘤依赖
虽然Spring
已懒加载,但是依赖很乱,往往依赖一个服务,又要注入很多的类,而且很多的业务的类,都写了@PostConstruct
,如果里面包含业务代码,例如查库啊之类的,你就呵呵吧。一次Spring启动能给你跑100条Sql,能不慢吗?
来,壮士断腕,把这些毒瘤,会预先加载的类,选一些不重要的在单测不需要用的都做个Mock,不要让这个拖垮我们的环境!
精益求精,搜寻日志,发现异常类加载超过10s,来魔改
这时候,其实一次单测已经在30s就可以搞定了,但是本着有点追求的想法,还是想再优化一下。
突然发现有一个可疑的日志
我们用的Cat
做监控,我们项目里有很多Cat
打点的工具类,只要跑到一个打点上,Cat就会开始加载(明明连不上),但是这一步骤估计是IO
之类的东西,加载一下居然花了10几秒,我的天,肯定要干掉!
怎么干呢?因为这些打点是耦合在代码里的,不好动,这时候想到的解决方案就是看看Cat
能不能关掉,后来冲浪了一番,发现我们这个旧版本没办法关。怎么办呢?被逼出来的
在代码目录里,搞个同名类,覆盖原有类,让他默认打点的时候不要初始化。魔改一把,生效!美滋滋!
classLoader默认会读同名最近的那个类
最后跑了一下单测,16s
,好爽!
-
3
-
总结一把
自从单测优化之后,后面制定规范让大家交付测试的时候自己先跑遍单测,这样就能有效的避免因为一些小错误返工 4、5次的尴尬,而且单测测的更全,更不容易出错,利已利民。
这里贴一下单测的核心类的注释:
多点时间陪陪家人
我:爽吗?我问对面的开发。
他:太爽了!
我笑了笑,深藏功与名(:
↓↓
作者:小之Evan@票牛网
掘金:https://juejin.im/user/5a7b9c106fb9a063417b182d
加入星球特权
1、从前端到后端玩转Spring Cloud
2、实战分库分表中间件Sharding-JDBC
3、实战分布式任务调度框架Elastic Job
4、配置中心Apollo实战
5、高并发解决方案之缓存
6、更多课程等你来解锁,20+课程
务实优化:将本地单元测试Spring启动速度从1分半优化到16秒,全流程详解相关推荐
- Spring 框架基础(06):Mvc架构模式简介,执行流程详解
本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...
- Spring Boot 2.x基础教程:默认数据源Hikari的配置详解
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 翟永超 来源 | http://blog.di ...
- java处理请求的流程_Java Spring mvc请求处理流程详解
Spring mvc请求处理流程详解 前言 spring mvc框架相信很多人都很熟悉了,关于这方面的资料也是一搜一大把.但是感觉讲的都不是很细致,让很多初学者都云里雾里的.本人也是这样,之前研究过, ...
- Spring中,applicationContext.xml 配置文件在web.xml中的配置详解
Spring中,applicationContext.xml 配置文件在web.xml中的配置详解 2016年10月04日 15:22:26 阅读数:7936 转自http://www.cnblogs ...
- 【线上沙龙直播报名】App 启动流程详解及其优化
点击上方"公众号"可以订阅哦 [美团点评技术沙龙Online]是美团点评技术团队推出的线上分享课程,每月2-3期,采用目前最火热的线上直播形式,邀请美团点评技术专家,面向互联网技术 ...
- GitHub轻松阅读微服务实战项目流程详解【第二天:API网关的设计与实现】
Two Day 1.配置文件精解 (1)bootstrap.yml文件 (2)nacos中关于gateway的配置信息 (3)applicaton.properties白名单配置 2.代码详解 (1) ...
- Spring Boot项目(Maven\Gradle)三种启动方式及后台运行详解
Spring Boot项目三种启动方式及后台运行详解 1 Spring Boot项目三种启动方法 运行Application.java类中的Main方法 项目管理工具启动 Maven项目:mvn sp ...
- 【笔记】spring的注解回顾,springboot-restful项目结构介绍 springboot-freemarker ⼯程配置详解
注解 学Spring boot有一阵子了,总结一下它的注解. @Controller :修饰class,⽤来创建处理http请求的对象 @RestController :Spring4之后加⼊的注解, ...
- Spring源码之启动过程(四)—— Bean的实例化详解
前面,我们把Bean的生命周期做了一个概述和梳理,为的是更深刻的理解容器启动及Bean的生命周期,最主要的是Bean的实例化过程,没有看过的,可以进去先看一下(文章链接:Spring源码之Bean的生 ...
最新文章
- 10 个深恶痛绝的 Java 异常。。
- 1043. 输出PATest(20)
- asp.net + winform + log4net 使用示例|using log4net with asp.net/winform
- C语言面试题(四)--------------------网上题目
- 玩美自由行体验报告 | 手摸手产品研究院
- 面向消息的中间件 (Message-Oriented Middleware, MOM)
- 这些数学趣图,数学老师看了后会怎么想?
- ubuntu进入桌面自动启动脚本_在 Ubuntu 下开机自启动自己的 QT 程序而不启动 Ubuntu 的桌面...
- Lockdoor Framework:一套自带大量网络安全资源的渗透测试框架
- 装箱问题(洛谷-P1049)
- Load data local infile
- SAP BTP 简介以及演化历史
- ubuntu20.4 微信,qq ,等安装安装教程
- 修复苹果电脑运行过程中出现的声音、触摸板失灵、键盘错键、光标乱窜问题
- 招商银行笔试题 公司年会
- vue element ui合并表格(合并某列的行数据)
- python画高德地图
- ubuntu下修复U盘并格式化
- Unity 2D Spine 外发光实现思路
- Linux命令rm -rf /无法完全删除问题处理