源码:Springboot的启动流程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

springboot2.5.6版本


入口

public static void main(String[] args) {
     SpringApplication.run(KafkaMain.class, args);
}

一、SpringApplication构造器

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
	Assert.notNull(primarySources, "PrimarySources must not be null");
	this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
	//1.获取应用类型
	this.webApplicationType = WebApplicationType.deduceFromClasspath();
	//2.加载META-INF/spring.factories下所有的 BootstrapRegistryInitializer
	this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
	//3.加载META-INF/spring.factories下所有的 ApplicationContextInitializer 初始化器
	setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
	//4.加载META-INF/spring.factories 下所有的 ApplicationListener 监听器
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	//5.检查启动类
	this.mainApplicationClass = deduceMainApplicationClass();
}

我需要了解spring内置注入的这些类是做什么的:
BootstrapRegistryInitializer

ApplicationContextInitializer
添加的初始化器

ApplicationListener
添加的监听器
在这里插入图片描述

二 run

//运行 Spring 应用程序,创建并刷新一个新的ApplicationContext 
public ConfigurableApplicationContext run(String... args) {
	//记录程序运行时间
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	DefaultBootstrapContext bootstrapContext = createBootstrapContext();
	//ConfigurableApplicationContext Spring 的上下文
	ConfigurableApplicationContext context = null;
	configureHeadlessProperty();
	//加载META-INF/spring.factories下所有的 SpringApplicationRunListene
	SpringApplicationRunListeners listeners = getRunListeners(args);
	//发布应用启动事件 触发LoggingApplicationListener监听器
	listeners.starting(bootstrapContext, this.mainApplicationClass);
	try {
		//存储args
		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);
		}
		listeners.started(context);
		//容器刷新完成 回调ApplicationRunner  CommandLineRunner
		callRunners(context, applicationArguments);
	} catch (Throwable ex) {
		handleRunFailure(context, ex, listeners);
		throw new IllegalStateException(ex);
	}

	try {
		listeners.running(context);
	} catch (Throwable ex) {
		handleRunFailure(context, ex, null);
		throw new IllegalStateException(ex);
	}
	return context;
}

三 prepareEnvironment()

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
												   DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
	// 获取或者创建 environment。这里获取类型是 StandardServletEnvironment
	ConfigurableEnvironment environment = getOrCreateEnvironment();
	// 将入参配置到环境配置中
	configureEnvironment(environment, applicationArguments.getSourceArgs());
	ConfigurationPropertySources.attach(environment);
	//发布环境准备时间ApplicationEnvironmentPreparedEvent, 触发EnvironmentPostProcessorApplicationListener监听器
	listeners.environmentPrepared(bootstrapContext, environment);
	DefaultPropertiesPropertySource.moveToEnd(environment);
	Assert.state(!environment.containsProperty("spring.main.environment-prefix"),
			"Environment prefix cannot be set via properties.");
	bindToSpringApplication(environment);
	if (!this.isCustomEnvironment) {
		environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
				deduceEnvironmentClass());
	}
	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);
	//应用 SpringApplication 构造器中加载的ApplicationContextInitializer
	applyInitializers(context);
	//发布 容器 初始化完成事件ApplicationContextInitializedEvent,bean定义被加载之前
	listeners.contextPrepared(context);
	bootstrapContext.close(context);
	if (this.logStartupInfo) {
		logStartupInfo(context.getParent() == null);
		logStartupProfileInfo(context);
	}
	// Add boot specific singleton beans
	ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
	beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
	if (printedBanner != null) {
		beanFactory.registerSingleton("springBootBanner", printedBanner);
	}
	if (beanFactory instanceof DefaultListableBeanFactory) {
		((DefaultListableBeanFactory) beanFactory)
				.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
	}
	if (this.lazyInitialization) {
		context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");
	// 这里将启动类加入到 beanDefinitionMap 中,为后续的自动化配置做好了基础
	load(context, sources.toArray(new Object[0]));
	//发布应用准备事件ApplicationPreparedEvent
	listeners.contextLoaded(context);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值