1.springboot程序运行,
1.第一步:进入run方法:
do: new SpringApplication 对象

第二步:调用SpringApplication 初始化方法初始化

图片的java代码分别对应下面的1-8
1:给SpringApplication的resourceLoader(资源加载器)赋值
2:判断入口主程序不能为空(类似参数的非空判断)
3:把主来源(SpringApplication )放到LinkedHashSet集合里面(有序并去重)
4:判断应用启动的类型:
4.1 NONE(应用程序不应该作为web应用程序运行,也不应该启动嵌入式web服务器。) 什么都没有,正常流程走,不额外的启动web容器
4.2 SERVLET(应用程序应该作为一个基于servlet的web应用程序运行,并且应该启动一个嵌入式servlet web服务器。) 基于servlet的web程序,需要启动内嵌的servletweb容器
4.3 REACTIVE(应用程序应该作为响应式web应用程序运行,并且应该启动嵌入式响应式web服务器。) 基于reactive的web程序
5:调用getSpringFactoriesInstances方法给SpringApplication的bootstrappers(引导程序)赋值

5.1 调用getClassLoader方法,获取一个classloader(第二步的1. 即: 之前给SpringApplication的resourceLoader(资源加载器)赋值。在这里面被调用了,因为之前赋值为null,所以这里运行getClassLoader方法后,会调用ClassUtils.getDefaultClassLoader()返回一个默认的ClassLoader)

5.2 调用SpringFactoriesLoader.loadFactoryNames方法(该方法会去从类路径中所有的META-INF/spring.factories的文件加载所有的类名)获取类的名称放到set集合(去重,使用名称并确保唯一,以防止重复)

5.3调用 createSpringFactoriesInstances方法根据type(type=Bootstrapper.class), parameterTypes, classLoader, args, names参数创建对应的springfactory实例。
5.4 调用AnnotationAwareOrderComparator.sort方法把这些springfactory实例排序
6.设置初始化器(Initializer): 调用getSpringFactoriesInstances方法根据type(type=ApplicationContextInitializer.class), parameterTypes, classLoader, args, names参数创建对应的springfactory实例。(举一个ApplicationContextInitializer在META-INF/spring.factories的某个文件内容如下图)

由此可得出,我们自定义一个ApplicationContextInitializer只需要实现接口,在spring.factories文件中设置即可。
7.设置监听器(Listener):调用getSpringFactoriesInstances方法根据type(type=ApplicationListener.class), parameterTypes, classLoader, args, names参数创建对应的springfactory实例。(举一个ApplicationListener在META-INF/spring.factories的某个文件内容如下图)

8.调用deduceMainApplicationClass方法给SpringApplication的bootstrappers(主程序类)赋值

deduceMainApplicationClass方法:会从调用RuntimeException().getStackTrace()方法从堆栈跟踪目前运行的方法。然后从拿到的这些stackTrace里面比较是不是有一个方法叫做main,如果有那么就把该方法对应的stackTrace的类名称拿到并用 Class.forName得到该class 返回。所以此时SpringApplication的bootstrappers(主程序类)的赋值会为com.huaru.springboot.SpringbootApplication。如下图

至此new SpringApplication(primarySources)源码分析完成。
下面分析new SpringApplication(primarySources)调用.run(args)方法源码
