前言

基于上次沸点7天打卡,这边给大家简单的讲解下我理解的启动流程(细枝末节可能被我给pass掉,毕竟是Spring啊,本次基于spring-boot-starter-parent~2.1.6.RELEASE)。

流程启动

  这里讲解的是Spring启动的一部分相关,目前里面涉及到的是一个简单的一个Web工程。

SpringBoot启动流程(1) | 七日打卡_SpringBoot

那我们就从SpringApplication.run(ServiceApplication.class, args);开始:

流程一

  方法进去首先new了个对象:new SpringApplication(primarySources),让我们看看里面有哪些东西进行处理

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));		this.mainApplicationClass = deduceMainApplicationClass();
	}复制代码

上述代码中:

  1. primarySources则是当前用户启动类类型。
  2. webApplicationType则是判断当前运行环境。共有三种选择。

SpringBoot启动流程(1) | 七日打卡_SpringBoot_02

  1. 在当前类加载器或者环境变量中META-INF/spring.factories搜寻类型为ApplicationContextInitializer的类,并将其加入当前属性变量集合中。
  2. 同3而言,搜寻类型为ApplicationListener的类,将其加入当前属性变量中(此时通过类加载器缓存集合中取,不需要再次扫描文件,3已经将所有配置加入到类加载器缓存中)

流程二

  接下来就是实例的run方法进行,这里挑选出一部分。

		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);复制代码
  1. StopWatch的作用就是计时。

  2. configureHeadlessProperty()用于系统的配置模式。Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标。

  3. getRunListeners(args)从当前ClassLoader下面META-INF/spring.factories或者从系统资源里面获取名称-在通过反射进行创建实例(EventPublishingRunListener),这里也是从ClassLoader缓存中读取。

  4. new DefaultApplicationArguments(args)构造命令行启动参数对象。

  5. prepareEnvironment(listeners, applicationArguments)这个方法里面主要为了Environment环境的创建准备。

    1. 根据webApplicationType类型,创建出对应的环境Bean(这里是new StandardServletEnvironment())。
    2. 添加类型转化器-ApplicationConversionService。(双锁volatile实例校验)。
    3. 在此应用程序的环境中添加、删除或重新排序任何propertsource,也就是将main中的args附加在PropertySources中。
    4. environment设置初始ActiveProfiles。
    5. listeners开始传播environmentPrepared准备好的事件(设置systemEnvironment以及加载当前Resource下的配置文件到环境中)。
    6. 将环境对象绑定至SpringApplication。
    7. 判断是否是自定义环境,是否将给定的环境转换为给定的标准环境类型。
    8. PropertySourceList队首添加SpringConfigurationPropertySources配置(使环境管理的每个PropertySource适应一个ConfigurationPropertySource)。
  6. 设置spring.beaninfo.ignore=true(值为true跳过了对BeanInfo类的搜索(通常用于在应用程序中首先没有为bean定义此类的场景))。

  7. banner资源获取判断打印。

上述的代码片段中完整的讲述了项目启动的一部分过程(细枝末微的可能没有提及到),不过环境配置组成也说的很多部分,其实主要关注如何加载Bean到容器中以及事件通知之后做了哪些事情。