SpringBoot中的SmartInitializingSingleton学习

一. 介绍

实现了 SmartInitializingSingleton 接口的 bean,当所有单例 bean 都已完全初始化后,该接口的 afterSingletonsInstantiated() 会被回调;

SmartInitializingSingleton 和 InitializingBean、@PostContruct 有啥区别呢?

  • SmartInitializingSingleton 是容器级别的,确保在所有 bean 初始化后才执行;
  • InitializingBean 和 @PostContruct 是 bean 级别的初始化回调;

二. 简单使用

先来看一下 SmartInitializingSingleton 接口;

可以看到该接口只有一个抽象方法;

public interface SmartInitializingSingleton {

    void afterSingletonsInstantiated();

}

举一个使用例子,定义一个 MySmartInitializingSingleton 类实现了 SmartInitializingSingleton 接口;

@Component
@Slf4j
public class MySmartInitializingSingleton implements SmartInitializingSingleton {

    @Override
    public void afterSingletonsInstantiated() {
        log.info("所有的单实例 bean 加载完成");
    }
}

容器启动时,在所有单实例都初始化完毕后,SmartInitializingSingleton 的 afterSingletonsInstantiated() 回调方法会执行;

三. 源码

我们需要知道 SmartInitializingSingleton 接口的 afterSingletonsInstantiated() 回调方法的执行时机,直接看 SpringBoot 项目的执行入口,也就是 SpringApplication.run();

// -------------------------- SpringApplication -----------------------------
public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();
    DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
    ConfigurableApplicationContext context = null;
    this.configureHeadlessProperty();
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    listeners.starting(bootstrapContext, this.mainApplicationClass);

    try {
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        this.configureIgnoreBeanInfo(environment);
        Banner printedBanner = this.printBanner(environment);
        context = this.createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        
        // 刷新 context 容器对象
        this.refreshContext(context);
        this.afterRefresh(context, applicationArguments);
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
  

        listeners.started(context, timeTakenToStartup);
        this.callRunners(context, applicationArguments);
    } catch (Throwable var12) {
        this.handleRunFailure(context, var12, listeners);
        throw new IllegalStateException(var12);
    }

    try {
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
        // 返回容器对象
        return context;
    } catch (Throwable var11) {
        this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var11);
    }
}



// -------------------------- SpringApplication -----------------------------
protected void refresh(ConfigurableApplicationContext applicationContext) {
    applicationContext.refresh();
}




// ------------------------ AbstractApplicationContext ------------------------
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();

        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        prepareBeanFactory(beanFactory);

        try {
            postProcessBeanFactory(beanFactory);

            invokeBeanFactoryPostProcessors(beanFactory);

            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            initMessageSource();

            initApplicationEventMulticaster();

            onRefresh();

            registerListeners();

            // 我们主要看这个方法
            // 该方法将所有非懒夹杂单实例 bean 对象初始化并放到 beanFactory 容器中
            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }
    }
}



// ------------------------ AbstractApplicationContext ------------------------
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // ......
    
    // 将所有的非懒加载单例 bean 初始化并放入到 beanFactory 容器中
    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}

核心方法是 beanFactory.preInstantiateSingletons();

public void preInstantiateSingletons() throws BeansException {
    if (logger.isTraceEnabled()) {
        logger.trace("Pre-instantiating singletons in " + this);
    }

    // 1. 拿到所有的 beanDefinitionNames,可以看到它是一个有先后顺序的 List
    List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

    // 2. 初始化所有的非懒加载单实例对象
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            if (isFactoryBean(beanName)) {
                // ...
                // FactoryBean
            }
            else {
                getBean(beanName);
            }
        }
    }

    // 3. 再次遍历 beanNames,
    // 执行 SmartInitializingSingleton.afterSingletonsInstantiated()
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            SmartInitializingSingleton smartSingleton = singletonInstance;
            smartSingleton.afterSingletonsInstantiated();
        }
    }
}

至此,SmartInitializingSingleton.afterSingletonsInstantiated() 执行时机完毕;

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值