【Spring-Boot】源码 简解析 之 启动流程

断点源码

只分析主要方法
源码版本:1.5.10

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

@SpringBootApplication包含以下三个注解
// 使用JavaConfig形式,不用xml
@SpringBootConfiguration
// 开启自动配置
@EnableAutoConfiguration
// 自动包扫描
@ComponentScan
1. initialize方法
private void initialize(Object[] sources) {

		// 1.初始化成员变量sources
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
		
		// 2.初始化成员变量webEnvironment,判断应用类型
		// javax.servlet.Servlet 或者 org.springframework.web.context.ConfigurableWebApplicationContext
		this.webEnvironment = deduceWebEnvironment();
		
		// 3.初始化成员变量initializers
		// spring.factories文件中key为ApplicationContextInitializer的类实例化
		// 设置到SpringApplication的initializers属性中,找出所有的应用程序初始化器
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));

		// 4.初始化成员变量listeners
		// spring.factories文件中key为ApplicationListener的类实例化
		// 设置到SpringApplication的listeners属性中,找出所有的应用程序事件监听器 
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		
		// 5.初始化成员变量mainApplicationClass,找应用的入口类
		this.mainApplicationClass = deduceMainApplicationClass();
	}
2. run方法
public ConfigurableApplicationContext run(String... args) {

		// 1.开始记录时间
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;

		// 2.设置java.awt.headless系统属性为true
		configureHeadlessProperty();
		
		// 3.获取SpringApplicationRunListeners,内部只有一个EventPublishingRunListener
		SpringApplicationRunListeners listeners = getRunListeners(args);
		
		// 4.接受ApplicationStartedEvent事件的listener会执行相应的操作
		listeners.starting();
		try {
			
			// 5.构造一个应用程序参数持有类
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			
			// 6.根据SpringApplicationRunListeners以及参数来准备环境 
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);

			// 7.打印logo
			Banner printedBanner = printBanner(environment);
			
			// 8.创建Spring容器
			context = createApplicationContext();
			
			// 9.创建异常分析器 
			analyzers = new FailureAnalyzers(context);

			// 10.Spring上下文前置处理
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			
			// 11.Spring上下文刷新
			refreshContext(context);

			// 12.容器创建完成之后执行额外一些操作
			afterRefresh(context, applicationArguments);
			
			// 13.广播出ApplicationReadyEvent事件给相应的监听器执行
			listeners.finished(context, null);

			// 14.停止计时
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}
3. run方法中的prepareContext方法
private void prepareContext(ConfigurableApplicationContext context,
			ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments, Banner printedBanner) {

		// 1.把环境和上下文关联起来
		context.setEnvironment(environment);

		// 2.为上下文配置Bean生成器以及资源加载器
		postProcessApplicationContext(context);

		// 3.调用初始化器
		applyInitializers(context);

		// 4.触发Spring Boot启动过程的contextPrepared事件
		listeners.contextPrepared(context);
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}

		// Add boot specific singleton beans
		// 5.添加两个Spring Boot中的特殊单例Bean:springApplicationArguments和springBootBanner
		context.getBeanFactory().registerSingleton("springApplicationArguments",
				applicationArguments);
		if (printedBanner != null) {
			context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
		}

		// Load the sources
		// 6.加载sources:对于DemoApplication而言,这里的sources集合只包含了它一个class对象
		Set<Object> sources = getSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		
		// 7.加载动作:构造BeanDefinitionLoader并完成Bean定义的加载
		load(context, sources.toArray(new Object[sources.size()]));
		
		// 8.触发Spring Boot启动过程的contextLoaded事件
		listeners.contextLoaded(context);
	}
    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/Q1013331Q/article/details/80198546
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞