网站Logo GESONG

SpringBoot启动过程

gesong
5
2025-09-01

SpringApplication.run

在应用启动类中调用SpringApplication.run方法,最终会new一个SpringApplication实例,再调用实例的run方法

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return (new SpringApplication(primarySources)).run(args);
}

实例化SpringApplication

先看一下实例化SpringApplication过程

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
    // 将启动类设置为primarySources 
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 推断web应用类型,判断是webFlux还是servlet
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // 从spring.factories中读取BootstrapRegistryInitializer并赋值给bootstrapRegistryInitializers(读取结果会缓存到一个Map中,避免重复读取)
	this.bootstrapRegistryInitializers = new ArrayList<>(
			getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    // 从spring.factories中读取ApplicationContextInitializer并赋值给initializers
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 从spring.factories中读取ApplicationListener并赋值给listeners
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 根据栈信息推断Main方法所在的类
	this.mainApplicationClass = deduceMainApplicationClass();
}

SpringApplication实例对象的run方法

启动整体流程在run方法中,逐行添加注释说明

public ConfigurableApplicationContext run(String... args) {
    Startup startup = SpringApplication.Startup.create();
    if (this.registerShutdownHook) {
        shutdownHook.enableShutdownHookAddition();
    }
    // 创建DefaultBootstrapContext启动器,在其中会遍历执行bootstrapRegistryInitializers(没有默认实现,是SpringBoot提供的扩展点)
    DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
    ConfigurableApplicationContext context = null;
    // 设置headless模式
    this.configureHeadlessProperty();
    // 获取运行监听器的组件
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    // 执行监听器,发布事件ApplicationStartingEvent
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
        // 获取应用参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 预初始化环境:读取环境变量,读取配置文件信息(基于监听器)
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        // 打印banner
        Banner printedBanner = this.printBanner(environment);
        // 创建容器上下文AnnotationConfigServletWebServerApplicationContext
        context = this.createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        // 预初始化上下文
        this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        // 刷新上下文,最后会调用spring容器的refresh方法
        this.refreshContext(context);
        this.afterRefresh(context, applicationArguments);
        startup.started();
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), startup);
        }

        listeners.started(context, startup.timeTakenToStarted());
        this.callRunners(context, applicationArguments);
    } catch (Throwable ex) {
        throw this.handleRunFailure(context, ex, listeners);
    }

    try {
        if (context.isRunning()) {
            listeners.ready(context, startup.ready());
        }

        return context;
    } catch (Throwable ex) {
        throw this.handleRunFailure(context, ex, (SpringApplicationRunListeners)null);
    }
}

prepareEnvironment方法

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// Create and configure the environment
        // 根据webApplicationType创建Environment,创建时会读取java环境变量和系统环境变量
		ConfigurableEnvironment environment = getOrCreateEnvironment();
        // 将命令行参数读取到环境变量中
		configureEnvironment(environment, applicationArguments.getSourceArgs());
        // 将@PropertiesSource的配置放在第一位,因为读取配置文件@PropertiesSource优先级是最低的
		ConfigurationPropertySources.attach(environment);
        // 发布事件ApplicationEnvironmentPreparedEvent,SpringBoot内置监听器EnvironmentPostProcessorApplicationListener监听该事件读取配置文件信息
		listeners.environmentPrepared(bootstrapContext, environment);
		DefaultPropertiesPropertySource.moveToEnd(environment);
		Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
				"Environment prefix cannot be set via properties.");
        // 将spring.main开头的配置信息绑定到SpringApplication
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			EnvironmentConverter environmentConverter = new EnvironmentConverter(getClassLoader());
			environment = environmentConverter.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
		}
       // 更新@PropertiesSource
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

prepareContext方法

	private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);
		postProcessApplicationContext(context);
		addAotGeneratedInitializerIfNecessary(this.initializers);
        // 执行Initializers
		applyInitializers(context);
        // 发布事件ApplicationContextInitializedEvent
		listeners.contextPrepared(context);
        // 发布事件BootstrapContextClosedEvent
		bootstrapContext.close(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
        // 获取beanFactory
		ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 将applicationArguments注册成一个单例bean
		beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
		if (printedBanner != null) {
			beanFactory.registerSingleton("springBootBanner", printedBanner);
		}
		if (beanFactory instanceof AbstractAutowireCapableBeanFactory autowireCapableBeanFactory) {
			autowireCapableBeanFactory.setAllowCircularReferences(this.allowCircularReferences);
			if (beanFactory instanceof DefaultListableBeanFactory listableBeanFactory) {
		// 设置不允许bean定义覆盖	listableBeanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
			}
		}
        // 设置是否懒加载
		if (this.lazyInitialization) {
            // 添加BeanFactory后置处理器
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		if (this.keepAlive) {
            // 添加ApplicationListener
			context.addApplicationListener(new KeepAlive());
		}
        // 添加BeanFactory后置处理器
		context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
		if (!AotDetector.useGeneratedArtifacts()) {
			// Load the sources
			Set<Object> sources = getAllSources();
			Assert.notEmpty(sources, "Sources must not be empty");
            // 读取启动类(后续要根据配置类解析配置的所有bean)
			load(context, sources.toArray(new Object[0]));
		}
        // 发布事件ApplicationPreparedEvent
		listeners.contextLoaded(context);
	}

spring容器的refresh方法

参考:https://todo.liberties.top/archives/springxiang-guan

动物装饰