spring boot 源码解析 启动流程

Posted nealriver

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot 源码解析 启动流程相关的知识,希望对你有一定的参考价值。

spring boot 源码解析 启动流程

在面试过程中经常被问到过spring boot的启动流程,今天就翻一下源码整体看一下;

首先,新建一个启动类,可以看到是首先调用的SpringApplication的静态方法run

@SpringBootApplication
public class SourceReadApplillcation 

    public static void main(String[] args) 
        SpringApplication.run(SourceReadApplillcation.class,args);
    
  1. 这里传入启动类的class,然后调用SpringApplication的构造函数new一个实例,接着调用run方法;
public static ConfigurableApplicationContext run(Class<?> primarySource,
            String... args) 
        return run(new Class<?>[]  primarySource , args);
public static ConfigurableApplicationContext run(Class<?>[] primarySources,
            String[] args) 
        return new SpringApplication(primarySources).run(args);
public SpringApplication(Class<?>... primarySources) 
        this(null, primarySources);


    
@SuppressWarnings( "unchecked", "rawtypes" )
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) 
    this.resourceLoader = resourceLoader;
    
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //推断web应用类型;
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //设置初始化器,从META-INF/spring.factories读取ApplicationContextInitializer
    //配置的值,读取详情后续研究
    setInitializers((Collection) getSpringFactoriesInstances(
            ApplicationContextInitializer.class));
    //设置监听器,同上,读取ApplicationListener配置的值
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //设置应用main启动类
    this.mainApplicationClass = deduceMainApplicationClass();

负责启动SpringBoot的主要方法

public ConfigurableApplicationContext run(String... args) 
    //计时器,主要为了统计消耗时间
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    
    //初始化应用上下文和异常报告集合
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    
    //设置java.awt.headless模式为true
    onfigureHeadlessProperty();
    
    //设置并启动META-INF/spring.factories下SpringApplicationRunListener配置的监听器
    //这里为EventPublishingRunListener,会通过反射调用其构造函数进行初始化
    //并将一开始设置的监听器保存到AbstractApplicationEventMulticaster的
    //内部类ListenerRetriever中,详情后续
    SpringApplicationRunListeners listeners = getRunListeners(args);
    //出发监听器开始启动事件
    listeners.starting();
    try 
        //初始化应用参数,例如启动设置的命令行参数等,可以通过这个类获取
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                args);
        //准备运行环境
        ConfigurableEnvironment environment = prepareEnvironment(listeners,
                applicationArguments);
        configureIgnoreBeanInfo(environment);
        //打印banner
        Banner printedBanner = printBanner(environment);
        //创建上下文,Springboot他默认为AnnotationConfigApplicationContext
        context = createApplicationContext();
        //准备异常报告
        exceptionReporters = getSpringFactoriesInstances(
                SpringBootExceptionReporter.class,
                new Class[]  ConfigurableApplicationContext.class , context);
        //准备上下文
        prepareContext(context, environment, listeners, applicationArguments,
                printedBanner);
        //刷新上下文
        refreshContext(context);
        //上下文刷新后置处理(空方法)
        afterRefresh(context, applicationArguments);
        //计时统计结束
        stopWatch.stop();
        
        if (this.logStartupInfo) 
            new StartupInfoLogger(this.mainApplicationClass)
                    .logStarted(getApplicationLog(), stopWatch);
        
        //触发启动完成事件
        listeners.started(context);
        callRunners(context, applicationArguments);
    
    catch (Throwable ex) 
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    
    try 
        //触发运行事件
        listeners.running(context);
    
    catch (Throwable ex) 
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    
    return context;

整个启动流程大体就是这样,先有一个整体的概念,其中实现细节很庞杂,后续逐一研究

以上是关于spring boot 源码解析 启动流程的主要内容,如果未能解决你的问题,请参考以下文章

Dubbo启动源码解析一

Spring Boot 启动源码解析系列六:执行启动方法一

苞米豆源码解析一: 动态注入

Spring Boot 启动源码解析二

Spring Boot 启动源码解析二

spring boot 2.1.7启动过程源码解析