在Spring6.2版本后,支持了异步初始化。
什么是异步初始化?见名知意,就是将Spring项目的初始化过程中的Bean通过异步加载的方式提高启动速度。
在业务系统中通常启动不会特别耗时,但也可以将系统启动过程中需要耗时初始化的Bean通过异步将其并行初始化,节省部分启动时间。本文作为学习Why哥文章之后的简单使用记录。
模拟初始化Bean耗时
ABean
@Slf4j
public class TestABean {
@SneakyThrows
public TestABean() {
log.info("A Bean开始初始化");
TimeUnit.SECONDS.sleep(5);
log.info("A Bean初始化完成");
}
}
BBean
@Slf4j
public class TestBBean {
@SneakyThrows
public TestBBean() {
log.info("B Bean开始初始化");
TimeUnit.SECONDS.sleep(6);
log.info("B Bean初始化完成");
}
}
配置类
@Configuration
public class RegisterConfiguration {
@Bean
public TestABean testABean() {
return new TestABean();
}
@Bean
public TestBBean testBBean() {
return new TestBBean();
}
}
启动类
@Slf4j
@ComponentScan("top.imyzt.learning.spring.startup")
public class Application {
public static void main(String[] args) {
StopWatch stopWatch = new StopWatch("Spring启动");
stopWatch.start();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}
}
启动日志
21:39:33.658 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testABean'
21:39:33.663 [main] INFO top.imyzt.learning.spring.startup.core.TestABean - A Bean开始初始化
21:39:38.667 [main] INFO top.imyzt.learning.spring.startup.core.TestABean - A Bean初始化完成
21:39:38.669 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testBBean'
21:39:38.670 [main] INFO top.imyzt.learning.spring.startup.core.TestBBean - B Bean开始初始化
21:39:44.673 [main] INFO top.imyzt.learning.spring.startup.core.TestBBean - B Bean初始化完成
StopWatch 'Spring启动': 11.555947229 seconds
------------------------------------------
Seconds % Task name
------------------------------------------
11.55594723 100%
小结
可以看到,在常规情况下,A和B Bean是串行初始化的,整个初始化耗时11.5s。
异步初始化
在Spring6.2版本中,@Bean注解引入了一个新的属性:bootstrap,默认Bean.Bootstrap.DEFAULT时为串行初始化,当指定为Bean.Bootstrap.BACKGROUND时,Spring会尝试异步初始化该Bean,但是需要配置一个名为bootstrapExecutor的线程池,用作异步初始化时所需的线程。
只需要将配置类稍作修改,就可以将指定的Bean进行异步初始化:
@Configuration
public class RegisterConfiguration {
@Bean(bootstrap = Bean.Bootstrap.BACKGROUND)
public TestABean testABean() {
return new TestABean();
}
@Bean(bootstrap = Bean.Bootstrap.BACKGROUND)
public TestBBean testBBean() {
return new TestBBean();
}
@Bean()
public Executor bootstrapExecutor() {
return new ThreadPoolExecutor(2, 10, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(1024));
}
}
然后我们再查看启动效果:
21:53:49.023 [pool-1-thread-1] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testABean'
21:53:49.024 [pool-1-thread-1] INFO top.imyzt.learning.spring.startup.core.TestABean - A Bean开始初始化
21:53:49.025 [pool-1-thread-2] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testBBean'
21:53:49.026 [pool-1-thread-2] INFO top.imyzt.learning.spring.startup.core.TestBBean - B Bean开始初始化
21:53:54.029 [pool-1-thread-1] INFO top.imyzt.learning.spring.startup.core.TestABean - A Bean初始化完成
21:53:55.031 [pool-1-thread-2] INFO top.imyzt.learning.spring.startup.core.TestBBean - B Bean初始化完成
StopWatch 'Spring启动': 6.740055683 seconds
-----------------------------------------
Seconds % Task name
-----------------------------------------
6.740055683 100%
可以看到启动时间从11.5s降为6.7s,效果十分显著,在部分需要依赖外部或已知需要耗时初始化的Bean,可以通过此方法进行优化。“我可以不用,你不能没有”。
参考
13年过去了,Spring官方竟然真的支持Bean的异步初始化了!
博客对应代码
Read More ~
标签:#
Java developer
IDEA 2023 非常用配置
配置文件全部使用UTF-8
Editor-File Encodings,将所有内容均设置为UTF-8。
Create UTF-8 files 选择 with NO BOM,避免在创建文件前3个字节来标志为UTF-8文件。
参数提示
默认情况下,是没有参数提示的,需要手动开启。
Editor-General-Code Completion-Parameter Info
注释默认在当前缩进
默认情况下,自动补全注释是在最前面,可以通过:
Editor-Code Style-Java(其它语言位置类似)-Code Generation-Comment Code按如下图配置进行处理。
如果配置的内容,在新项目不生效,则注意此处
除了字体样式字体大小外,其它的配置IDEA官方认为,每个项目在创建时,可能都需要一些不同的配置,所以有很多内容都是跨项目不生效的(Maven、文件格式等),需要在此处配置(点进去和Settings一模一样,但是对应的是Next Project(新项目)的配置)
Read More ~
Java开发工具推荐
工具包
Google Guava
HuTool
Apache Commons(这玩意估计没人不知道了。)
工具类
AntPathMatcher
作用:URL路径匹配
?匹配一个字符
*匹配0个或多个字符
**匹配0个或多个目录
StopWatch
作用:方法耗时计算
该类Spring和Guava都有提供,用法大同小异
BeanCopier
作用:拷贝bean
比Apache和Spring提供的BeanUtils效率好点
注意点:
该方法与lombok提供的@Accessors(chain = true)注解冲突,在cglib最底层target调用set方法进行参数设置的时候,判断了set方法返回值是否为void,不为void不会进行赋值操作。
解决方法有2:
去掉@Accessors(chain = true)
使用org.springframework.beans.BeanUtils
Read More ~