springboot源码阅读系列1---启动

开始

springboot的启动入口非常直接,main方法里执行的run:

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

之后是初始化 SpringApplication,然后执行的run方法:
springboot源码阅读系列1---启动_第1张图片
同时,将启动入口的类,如Application.class作为参数传入到构造函数中去。
通常这个类执行一下过程:

  • 创建ApplicationContext实例
  • 注册CommandLinePropertySource 以暴露命令行参数作为Spring 的属性
  • 刷新上下文,加载单例bean

springboot源码阅读系列1---启动_第2张图片
那么核心的run方法就到了

public ConfigurableApplicationContext run(String... args) {
//   计时器
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		// 1 与生命周期相关,在Springboot启动过程启动监听器,自定义的Runner就在这里注册
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
		// 2 准备环境
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			//3  准备上下文
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			// 4 刷新上下文
			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, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

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

1 自定义的Runner就在这里注册在这里插入图片描述

在这里插入图片描述

2 环境有区分,普通Springboot环境,web环境以及Reactive环境

springboot源码阅读系列1---启动_第3张图片
springboot源码阅读系列1---启动_第4张图片
然后进行环境配置:

protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
		if (this.addConversionService) {
			ConversionService conversionService = ApplicationConversionService.getSharedInstance();
			environment.setConversionService((ConfigurableConversionService) conversionService);
		}
		configurePropertySources(environment, args);
		configureProfiles(environment, args);
	}

这里的addConversionService涉及转换服务,可以参考:
类型转换ApplicationConversionService
PropertySources的来源包括好几部分:
如果是命令行命令,加入到sources中
springboot源码阅读系列1---启动_第5张图片
优先级顺序:
1、commonLine 属性
2、servlet 上下文
3、servlet 配置文件
4、Jndi 属性源
5、java参数属性源。
6、环境变量属性源。
7、random属性源。
8、springboot 配置源(application-dev.yml 优先于application.yml)
springboot源码阅读系列1---启动_第6张图片
之后就开始设置profile

3 准备上下文

前面在准备上下文的时候,我以为使用web环境,初始化的上下文应该是AnnotationConfigServletWebServerApplicationContext,但是实际上下来的时候是AnnotationConfigApplicationContext
在这里插入图片描述

public AnnotationConfigServletWebServerApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);// 非常重要的扫描器
	}

下一篇 BD流程

你可能感兴趣的:(java)