spring boot 启动流程全解析--基于spring boot 2.1.9

1.Spirng boot 启动main 方法调用了SpringApplication的静态run方法

public static void main(String[] args) {

    SpringApplication.run(xxx.class, args);

}

 

//run方法中最终先调用了SpringApplication 的构造器,构造器如下所示
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {

    //指定resourceLoader

       this.resourceLoader = resourceLoader;



// 断言主类,并将主类赋给成员变量

    Assert.notNull(primarySources, "PrimarySources must not be null");

    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));

      

// 根据classpath下是否有对应的类判断web容器类型 (SERVLET、REACTIVE、NONE)

    this.webApplicationType = WebApplicationType.deduceFromClasspath();



// 根据各starter包下的META-INF/spring.factories文件找到所有的ApplicationContextInitializer 并赋值给成员变量

    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));



//  根据各starter包下的META-INF/spring.factories文件找到所有的ApplicationListener 并赋值给成员变量

    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));



// 推断出当前执行流中的含有main方法的类(主类)

    this.mainApplicationClass = deduceMainApplicationClass();

}



3.执行run方法

public ConfigurableApplicationContext run(String... args) {

// 创建并启动计时监控类

    StopWatch stopWatch = new StopWatch();

    stopWatch.start();



    ConfigurableApplicationContext context = null;

    Collection exceptionReporters = new ArrayList<>();

//设置系统属性 `java.awt.headless` 的值

    configureHeadlessProperty();



// 根据各starter包下的META-INF/spring.factories文件找到所有的SpringApplicationRunListener 类并执行starting方法

    SpringApplicationRunListeners listeners = getRunListeners(args);

    listeners.starting();





    try {

// 封装命令行参数

        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

//准备环境(下文细讲)

        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

        configureIgnoreBeanInfo(environment);

//打印banner

        Banner printedBanner = printBanner(environment);

//根据容器类型创建应用上下文

        context = createApplicationContext();

//准备异常报告器

        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,

                new Class[] { ConfigurableApplicationContext.class }, context);



//准备应用上下文

        prepareContext(context, environment, listeners, applicationArguments, printedBanner);



//刷新上下文环境 这里点开发现是调用AbstractApplicationContext的refresh方法,这属于spring 环境刷新方法,具体解释见https://www.jianshu.com/p/fca013ec1764

        refreshContext(context);



// 源码暂时是空的,可能是后期会增加一些功能

        afterRefresh(context, applicationArguments);



//停止计时器

        stopWatch.stop();



// 输出日志记录

        if (this.logStartupInfo) {

            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);

        }



//触发所有SpringApplicationRunListener 监听器的 started 事件方法

        listeners.started(context);



//触发所有继承了ApplicationRunner 和 CommandLineRunner的类的run方法

        callRunners(context, applicationArguments);

    }

    catch (Throwable ex) {

        handleRunFailure(context, ex, exceptionReporters, listeners);

        throw new IllegalStateException(ex);

    }

    try {

// 触发所有SpringApplicationRunListener 监听器的 running 方法

        listeners.running(context);

    }

    catch (Throwable ex) {

        handleRunFailure(context, ex, exceptionReporters, null);

        throw new IllegalStateException(ex);

    }

    return context;

}







这里对准备环境 和 准备上下文 方法进行详细解析



准备环境



private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,

        ApplicationArguments applicationArguments) {

    //1.根据容器类型创建不同的环境

    ConfigurableEnvironment environment = getOrCreateEnvironment();



//  2. 加载spring数据转换,并获取activeProfiles

    configureEnvironment(environment, applicationArguments.getSourceArgs());



//3执行SpringApplicationRunListener的 environmentPrepared方法

    listeners.environmentPrepared(environment);



//4.绑定环境到 spring application

    bindToSpringApplication(environment);

    if (!this.isCustomEnvironment) {

        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,

                deduceEnvironmentClass());

    }

// 5. 根据不同环境决定使用的配置

    ConfigurationPropertySources.attach(environment);

    return environment;

}



 准备上下文

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,

        SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {

// 绑定环境到上下文

    context.setEnvironment(environment);



// 配置上下文的 bean factory及资源加载器

    postProcessApplicationContext(context);



//应用所有ApplicationContextInitializer 的初始化方法

    applyInitializers(context);



//  触发所有 SpringApplicationRunListener 监听器的 contextPrepared 事件方法

    listeners.contextPrepared(context);

    if (this.logStartupInfo) {

        logStartupInfo(context.getParent() == null);

        logStartupProfileInfo(context);

    }

    // 加载两个特殊的bean

    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();

    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);

    if (printedBanner != null) {

        beanFactory.registerSingleton("springBootBanner", printedBanner);

    }

    if (beanFactory instanceof DefaultListableBeanFactory) {

        ((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);

    }

    // 加载资源

    Set sources = getAllSources();

    Assert.notEmpty(sources, "Sources must not be empty");

    load(context, sources.toArray(new Object[0]));



//  触发所有 SpringApplicationRunListener 监听器的 contextLoaded 事件方法

    listeners.contextLoaded(context);

}


 

你可能感兴趣的:(spring boot 启动流程全解析--基于spring boot 2.1.9)