SpringBoot配置原理(源码流程)

SpringBoot启动配置原理

几个重要的事件回调机制
配置在META-INF/spring.factories

  • ApplicationContextInitializer
  • SpringApplicationRunListener

只需要放在ioc容器中

  • ApplicationRunner
  • CommandLineRunner

启动流程

1. 创建SpringApplication对象

/**
 * Create a new {@link SpringApplication} instance. The application context will load
 * beans from the specified primary sources (see {@link SpringApplication class-level}
 * documentation for details. The instance can be customized before calling
 * {@link #run(String...)}.
 * @param resourceLoader the resource loader to use
 * @param primarySources the primary bean sources
 * @see #run(Class, String[])
 * @see #setSources(Set)
 */
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));
	//从类路径下找到META-INF/spring.factories配置的所有ApplicationListener
	setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
	//可以从多个配置类中找到有main方法的主配置类
	this.mainApplicationClass = deduceMainApplicationClass();
}

setInitializers

从所有包中找到对应的META-INF/spring.factories配置的所有ApplicationContextInitializer
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
setListeners

同一文件下找到ApplicationListener
在这里插入图片描述

在这里插入图片描述
找到主配置类

此处传入的是配置类,可以穿入多个,从中找到一个有Main方法的类当作主配置类。
在这里插入图片描述

2. 运行run方法

/**
 * Run the Spring application, creating and refreshing a new
 * {@link ApplicationContext}.
 * @param args the application arguments (usually passed from a Java main method)
 * @return a running {@link ApplicationContext}
 */
public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	//声明IoC容器为空
	ConfigurableApplicationContext context = null;
	Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
	configureHeadlessProperty();
	//获取SpringApplicationRunListener;从类路径下META-INF/spring.factories
	SpringApplicationRunListeners listeners = getRunListeners(args);
	//回调所有SpringApplicationRunListener.starting()方法
	listeners.starting();
	try {
		//封装命令行参数
		ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		//准备环境,创建完成后回调SpringApplicationRunListener.environmentPrepared()方法
		ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
		configureIgnoreBeanInfo(environment);
		//打印spring图标
		Banner printedBanner = printBanner(environment);
		
		//创建ApplicationContext:决定创建webioc还是普通ioc
		context = createApplicationContext();
		exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
				new Class[] { ConfigurableApplicationContext.class }, context);
		//准备上下文环境,传入ioc容器、环境、监听器;保存环境到ioc中;
		//而且applyInitializer()回调之前创建时获取的所有Initializer的initialize方法
		//回调所有的  SpringApplicationRunListener.contextPrepared()  方法
		//运行完毕后回调所有的  SpringApplicationRunListener.contextLoaded()  方法
		prepareContext(context, environment, listeners, applicationArguments, printedBanner);

		//刷新容器;ioc容器初始化,加载所有对象(如果是web应用还会创建嵌入式Tomcat)
		//扫描、创建、加载所有组件的地方
		refreshContext(context);
		//从ioc容器中获得所有的ApplicationRunner和CommandLineRunner进行回调
		//ApplicationRunner先回调,CommandLineRunner后回调,有优先级
		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);
	}
	//整个SpringBoot启动完成,返回启动的ioc
	return context;
}

在这里插入图片描述

private void prepareContext(ConfigurableApplicationContext context,
		ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
		ApplicationArguments applicationArguments, Banner printedBanner) {
	
	// 保存环境到 ioc容器中
	context.setEnvironment(environment);
	postProcessApplicationContext(context);
	
	// 获取所有初始化器,回调所有ApplicationContextInitializer的初始化方法
	applyInitializers(context);
	
	// 回调所有的listeners的准备方法
	listeners.contextPrepared(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);
	}
	// Load the sources
	Set<Object> sources = getAllSources();
	Assert.notEmpty(sources, "Sources must not be empty");
	load(context, sources.toArray(new Object[0]));

	// 执行完之后回调方法
	listeners.contextLoaded(context);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值