Bean 异步初始化,让你的应用启动飞起来

本文探讨了如何通过异步初始化Bean来提升Java应用的启动速度,特别是针对涉及网络IO的中间件Bean。文章详细介绍了异步初始化Bean的原理,包括如何自定义BeanFactory和BeanPostProcessor以支持异步执行init、afterPropertiesSet和@PostConstruct方法。同时,以HSF为例,解释了如何批量扫描和异步加载中间件Bean,以提高启动性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果你的系统启动耗时250s以上,文章思路应该可以帮到你。

一、背景

近期,在做应用启动提速相关工作的过程中,我们发现,应用启动速度主要的瓶颈在于bean的初始化过程(init,afterPropertiesSet方法的耗时)。很多中间件bean的初始化逻辑涉及到网络io,且在没有相互依赖的情况下串行执行。将这一部分中间件bean进行异步加载,是提升启动速度的一个探索方向。

二、解决方案

  1. 自动扫描可批量异步的中间件bean,而后,在bean的初始化阶段利用线程池并行执行其初始化逻辑。
  2. 允许使用方自行配置耗时bean以享受异步加速能力。(需使用方自行确认依赖关系满足异步条件)

三、原理

3.1 异步初始化原理

3.1.1 如何异步init和afterPropertiesSet?

3.1.1.1 这俩初始化方法在哪里执行的?

在AbstractAutowireCapableBeanFactory#invokeInitMethods方法(以下代码省略异常处理以及日志打印)

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)        throws Throwable {    // 先看bean是不是实现了InitializingBean,如果是则执行afterPropertiesSet方法。    boolean isInitializingBean = (bean instanceof InitializingBean);    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {        if (System.getSecurityManager() != null) {            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {                ((InitializingBean) bean).afterPropertiesSet();                return null;            }, getAccessControlContext());        } else {            ((InitializingBean) bean).afterPropertiesSet();        }    }    // xml定义的init方法    if (mbd != null && bean.getClass() != NullBean.class) {        String initMethodName = mbd.getInitMethodName();        if (StringUtils.hasLength(initMethodName) &&                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&                !mbd.isExternallyManagedInitMethod(initMethodName)) {            invokeCustomInitMethod(beanName, bean, mbd);        }    }}
  • 调用位置图

3.1.1.2 如何自定义该方法逻辑使其支持异步执行?

  • 很简单的想法

有没有可能,我可以替换原有的BeanFactory,换成我自定义的一个BeanFactory,然后我继承他,只是重写invokeInitMethods方法逻辑使其支持异步?像这样:

public class AsyncInitBeanFactory extends DefaultListableBeanFactory {
    private static final Logger logger = LoggerFactory.getLogger(AsyncInitBeanFactory.class);
    // 省略
    @Override    protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {        if (AsyncInitBeanNameContainer.MIDDLEWARE_ASYNC_HSF_BEAN_NAME.contains(beanName)) {            // hsf异步init            this.asyncCallInitMethods(TaskUtil.threadPool4HsfBean, beanName, bean, mbd);        } else if (AsyncInitBeanNameContainer.MIDDLEW
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值