03、SpringBoot 启动 执行SpringApplication的run方法 准备运行环境前 流程

目录Springboot源码学习目录
上文02、SpringBoot 启动 总流程
前言:本篇文章开始讲;SpringBoot的启动流程的第二部分,当前第二部分是核心逻辑,也分为几块进行讲解,分别是,准备运行环境前,准备运行环境,创建应用上下文,准备应用上下文,刷新应用上下文,刷新应用上下文后处理,本文主要讲解准备运行环境前的一些流程,是一些不太重要的流程,只是把run方法的大体脉络,以及源码展示一下,重点的从下一篇开始

一、启动总流程

    public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
        // 创建引导上下文
	DefaultBootstrapContext bootstrapContext = createBootstrapContext();
	ConfigurableApplicationContext context = null;
        // 配置应用为headless模式
        // Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标
	configureHeadlessProperty();
        // 获取Spring应用运行监听器,这里其实是初始化了一个广播器,将前面获取的所有的监听器注册到广播器中
        // 后续的流程中会触发各种事件
	SpringApplicationRunListeners listeners = getRunListeners(args);
        // 获取Spring应用运行监听器后,立刻发出第一个事件,标志着应用要开始启动了,进行最早的一些初始化工作
	listeners.starting(bootstrapContext, this.mainApplicationClass);
	try {
                // 封装启动参数
        	ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
                // 准备运行环境,对配置文件的解析就在这一步
		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		configureIgnoreBeanInfo(environment);
		Banner printedBanner = printBanner(environment);
                // 创建应用上下文
		context = createApplicationContext();
		context.setApplicationStartup(this.applicationStartup);
                // 准备应用上下文
		prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
                // 刷新应用上下文
		refreshContext(context);
                // 刷新应用上下文后处理
		afterRefresh(context, applicationArguments);
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
		}
                / 发出启动结束事件,上下文已刷新,应用程序已启动,但尚未调用CommandLineRunner和ApplicationRunner。
		listeners.started(context);
                // 执行runner的run方法
		callRunners(context, applicationArguments);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, listeners);
		throw new IllegalStateException(ex);
	}
	try {
                // 发出运行中事件,此时应用程序上下文已刷新,并且所有CommandLineRunner和ApplicationRunner都已调用
		listeners.running(context);
	}
	catch (Throwable ex) {
		handleRunFailure(context, ex, null);
		throw new IllegalStateException(ex);
	}
        // 返回最终构建的容器对象
	return context;
    }

二、创建引导上下文

    private DefaultBootstrapContext createBootstrapContext() {
        // 创建一个DefaultBootstrapContext对象
	DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
        // 前面的文章里提到实例化SpringApplication应用时,初始化了引导注册表初始化后增强器,在这里创建DefaultBootstrapContext对象后,就是对他进行增强的
	this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));		    
        return bootstrapContext;
    }

三、获取Spring应用运行监听器

    private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
        // 创建一个SpringApplicationRunListeners对象,里面里面存放里一个SpringApplicationRunListener(Spring应用程序运行监听器)集合
        // 获取的是SpringApplicationRunListener(Spring应用程序运行监听器)的方式和前面文章中
        // 应用程序监听器(ApplicationListener),应用程序上下文初始化后增强器(ApplicationContextInitializer),引导注册表初始化后增强器,的获取方法一样,从spring.factories 中获取指定类型的实现类集合
        // Spring应用程序运行监听器 和前面的 应用程序监听器 不是一个东西,Spring应用程序运行监听器只会在springboot启动的过程中生效,在启动的各个环节进行一些增强操作
        // 有些Spring应用程序运行监听器 中还会初始化一个 广播器,回调应用程序监听器
	return new SpringApplicationRunListeners(logger,
		getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
		this.applicationStartup);
    }
posted @ 2021-10-29 18:31  君子思  阅读(377)  评论(0)    收藏  举报