SpringBoot启动过程

@SpringBootApplication
public class Application {
	public static void main(String[] args) {
    	SpringApplication.run(Application.class, args);
		}
}java

SpringApplication静态方法run

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

只做了两件事:

  1. new SpringApplication对象
  2. 执行该对象的run方法

SpringApplication对象初始化

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		//	资源加载器,初始为 null
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// 确定应用程序类型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// 获取引导器
		//  META-INF/spring.factories 文件中找 org.springframework.boot.Bootstrapper
		// 寻找的顺序:classpath → spring-beans → boot-devtools → springboot → boot-autoconfigure
		this.bootstrapRegistryInitializers = getBootstrapRegistryInitializersFromSpringFactories();
		// 获取初始化器   META-INF/spring.factories 文件中找org.springframework.context.ApplicationContextInitializer
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		// 初始化监听器  META-INF/spring.factories 文件中找org.springframework.context.ApplicationListener
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// 设置运行主类
		this.mainApplicationClass = deduceMainApplicationClass();
	}

对象初始化的几件事情:

  1. 确定程序的应用类型(NONE,SERVLET,WEBFLUX)
  2. 解析META-INF/spring.factories文件
  3. 获取引导器,获取初始化器,获取监听器
  4. 设置运行时的主类
getBootstrapRegistryInitializersFromSpringFactories()详解
@SuppressWarnings("deprecation")
	private List<BootstrapRegistryInitializer> getBootstrapRegistryInitializersFromSpringFactories() {
		ArrayList<BootstrapRegistryInitializer> initializers = new ArrayList<>();
		getSpringFactoriesInstances(Bootstrapper.class).stream()
				.map((bootstrapper) -> ((BootstrapRegistryInitializer) bootstrapper::initialize))
				.forEach(initializers::add);
		initializers.addAll(getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
		return initializers;
	}

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// 加载所有spring.factories文件,并放入缓存,提升后续读取效率
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		// 通过反射将其初始化
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}
初始化初始化器ApplicationContextInitlializer/初始化监听器ApplicationListener

过程大致同上,只不过是从缓存获取spring.factories

run方法

public ConfigurableApplicationContext run(String... args) {
		// 定义时间watch
		StopWatch stopWatch = new StopWatch();
		// 启动时间计时
		stopWatch.start();
		// 创建引导上下文环境
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		// 进入headless
		configureHeadlessProperty();
		// 获取应用程序运行监听监听器,META-INF/spring.factories 文件中找 org.springframework.boot.SpringApplicationRunListener
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 监听器启动,遍历所有的运行监听器调用 starting 方法
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			// 参数
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			// 准备环境信息
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			// 配置忽略bean信息
			configureIgnoreBeanInfo(environment);
			// 打印banner
			Banner printedBanner = printBanner(environment);
			// 创建应用上下文容器,创建 IOC 容器
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			// 配置 IOC 容器的基本信息	
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			// 刷新 IOC 容器
			/* 1. Spring 的容器启动流程
			 * 2. invokeBeanFactoryPostProcessors(beanFactory):实现了自动装配
			 * 3. onRefresh():创建 WebServer 使用该接口
 			*/
			refreshContext(context);
			// 刷新后操作
			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, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			// 事件广播:容器开始运行
			listeners.running(context);
		}catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

	private DefaultBootstrapContext createBootstrapContext() {
		//创建默认的引导类环境
		DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
		// 遍历所有的引导器,调用其initialize方法,完成初始化设置
		this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
		return bootstrapContext;
	}

	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			DefaultBootstrapContext bootstrapContext, ApplicationArguments applicationArguments) {
		// 创建或返回基础环境信息对象 reative/servlet/default
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		// 读取所有配置源的属性值配置环境
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		// 属性值绑定环境信息
		ConfigurationPropertySources.attach(environment);
		// 运行监听器调用,environmentPrepared(),EventPublishingRunListener 发布事件通知所有的监听器当前环境准备完成
		listeners.environmentPrepared(bootstrapContext, environment);
		// 将defaultProperties属性移到配置源最后
		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;
	}

	private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {
		context.setEnvironment(environment);
		// 初始化beanName生成器
		postProcessApplicationContext(context);
		// 获取所有的初始化器调用 initialize() 方法进行初始化
		applyInitializers(context);
		// 所有的运行监听器调用 environmentPrepared() 方法,EventPublishingRunListener 发布事件通知 IOC 容器准备完成
		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");
		load(context, sources.toArray(new Object[0]));
		// 所有的运行监听器调用 contextLoaded() 方法,通知 IOC 加载完成
		listeners.contextLoaded(context);
	}

run方法核心操作:

  1. 定义时间watch,记录当前时间
  2. 创建引导上下文环境
  3. 获取所有的运行监听监听器,并启动
  4. 获取参数持有类
  5. 准备环境信息
  6. 配置忽略的bean信息
  7. 打印banner
  8. 创建ioc容器
  9. 配置ioc容器基本信息
  10. 刷新ioc容器(容器初始化、自动装配)
  11. 刷新后操作(给用户提供扩展空间)
  12. 记录启动时间,广播启动事件
  13. 执行后置runner