Springboot启动流程

闲来无事,串一下springboot3.0的启动流程,一己之见,可能有误。

1 启动入口
//启动方法,返回上下文对象,入参,配置类信息,启动参数,后续会new 一个SpringApplication对象执行run方法
SpringApplication.run(Application.class, args);
2 创建对象
//new SpringApplication对象

this.sources = new LinkedHashSet();
//打印banner的方法,控制台、日志、不打印
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;	//应该是注册虚拟机关闭钩子
this.additionalProfiles = Collections.emptySet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
//默认的上下文工厂,后续会由此对象生成Reactive或Servlet上下文
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
this.applicationStartup = ApplicationStartup.DEFAULT;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
//推断webApp类型,逻辑是先判断有没有REACTIVE的相关类文件,有的话则是REACTIVE,没有的话判断是否包含全部的servlet相关,全部包含则是SERVLET,否则返回NONE
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//通过SpringFactoriesLoader.forDefaultResourceLocation(this.getClassLoader()).load(type, argumentResolver)读取META-INF/spring.factories下的类信息
//不清楚,可能是要在启动前做某些事
this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
//设置上下文初始化
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听器
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//推断主类,通过当前程序的堆栈信息,通过是否包含"main"关键字进行判断
this.mainApplicationClass = this.deduceMainApplicationClass();
3 run方法
public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();
    //创建bootstrap上下文
    DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
    ConfigurableApplicationContext context = null;
    this.configureHeadlessProperty();
    //创建事件监听,由EventPublishingRunListener进行事件分发
    //会从当前SpringApplication对象对象中,拿出所有的监听者信息,进行事件分发
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    //发布事件
    listeners.starting(bootstrapContext, this.mainApplicationClass);

    try {
        //启动参数包装
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //创建环境,发布事件,
        //如果是cloud,会走BootstrapApplicationListener的监听方法,通过SpringApplicationBuilder先创建一个SpringApplication对象,先走一遍流程
        //由EnvironmentPostProcessorApplicationListener接收事件,找到对应的ConfigDataEnvironmentPostProcessor等处理器,进行环境信息填充
        //这里有一个很实用的方法:Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
        //大概意思就是,从环境中,绑定某些信息到当前对象,或者是一个List,Map等
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        //打印banner,判断打印类型,从环境中读取banner配置信息,如果没有取默认值banner.txt,如果还没有,就取构造时传递的SpringApplication对象中的banner对象,如果对象为null,取默认值SpringBootBanner
        Banner printedBanner = this.printBanner(environment);
        //创建上下文对象,通过上文推断的webApp类型进行创建
        context = this.createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        //准备上下文,注册一些单例bean、处理器,把传入的配置类转化为bean定义信息加入上下文,供后续创建bean
        this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        //刷新上下文,注册jvm虚拟机关闭钩子,可在关闭的时候发布关闭事件,执行销毁bean对象方法
        this.refreshContext(context);
        //完成刷新,什么也没做
        this.afterRefresh(context, applicationArguments);
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
        (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
        }
		//发布事件
        listeners.started(context, timeTakenToStartup);
        //执行实现ApplicationRunner和CommandLineRunner的启动方法
        this.callRunners(context, applicationArguments);
    } catch (Throwable var12) {
        if (var12 instanceof SpringApplication.AbandonedRunException) {
        throw var12;
        }

        this.handleRunFailure(context, var12, listeners);
        throw new IllegalStateException(var12);
    }

    try {
        if (context.isRunning()) {
        Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
        listeners.ready(context, timeTakenToReady);
        }

        return context;
    } catch (Throwable var11) {
        if (var11 instanceof SpringApplication.AbandonedRunException) {
        throw var11;
        } else {
        this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var11);
        }
    }
}
4 刷新上下文
public void refresh() throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
        //准备刷新
        this.prepareRefresh();
        //获取beanFactory,实现类是DefaultListableBeanFactory
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        //准备beanFactory,这一步会添加处理器等
        this.prepareBeanFactory(beanFactory);

        try {
            //beanFactory后置处理
            this.postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            //执行beanFactory的后置处理器
            //这一步的逻辑有点绕,处理BeanDefinitionRegistry和BeanFactoryPostProcessor
            //先执行BeanDefinitionRegistry,然后从beanFactory获取优先(有排序)的BeanDefinitionRegistry,再执行优先级较低、没有优先级的BeanDefinitionRegistry
            //然后执行BeanFactoryPostProcessor,执行的逻辑同上
            //在的SpringApplication对象的run方法的prepareContext方法的load方法中,创建BeanDefinitionLoader的构造方法中,添加了默认的处理器
            //这一步的BeanFactoryPostProcessor对象,由SpringApplication对象的applyInitializers方法加入的
            //如果有传入,则优先执行传入的处理器,然后从beanFactory里面获取处理器并执行
            //这一步会解析生成BeanDefinition
            //扫描启动类上的注解应该也是在这一步执行的,主要的核心逻辑应该在ConfigurationClassPostProcessor和ConfigurationClassParser类
            this.invokeBeanFactoryPostProcessors(beanFactory);
            //注册bean的处理器,处理逻辑同上
            this.registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();
            //初始化MessageSource,暂不清楚
            this.initMessageSource();
            //初始化事件分发器
            this.initApplicationEventMulticaster();
            //刷新,这一步如果是webApp类型,会在这里创建webServer,比如说TomcatServletWebServerFactory
            this.onRefresh();
            //注册事件监听者
            this.registerListeners();
            //创建bean,通过getBean的方法进行创建
            this.finishBeanFactoryInitialization(beanFactory);
            //完成刷新,发布事件
            this.finishRefresh();
        } catch (BeansException var10) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
            }

            this.destroyBeans();
            this.cancelRefresh(var10);
            throw var10;
        } finally {
            this.resetCommonCaches();
            contextRefresh.end();
            }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值