兄弟们跟我来,在入口出打上断点,开始DEBUG:
stepinto进入SpringApplication
接下来stepinto会提示我们选择进入SpringApplication构造器还是进入run()方法,IDEA会把他们以紫色标出
写在前面
创建SpringApplication干了哪些事:先说结论:
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();this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();}
- primarySources:保存当前主启动类信息
class com.atguigu.boot.Boot09HelloTestApplication - webApplicationType:使用工具类ClassUtils判定当前应用的类型。一般是Servlet类型,非Reactive类型
- bootstrappers:初始启动引导器List
:去spring.factories文件中找 org.springframework.boot.Bootstrapper - setInitializers:
ApplicationContextInitializer:去spring.factories找 ApplicationContextInitializer- List
> initializers
- List
- setListeners:
ApplicationListener:去spring.factories找 ApplicationListener- List
> listeners
- List

倘若stepinto的这一行代码有多个函数(构造方法也是函数),则IDEA会提示我们选择进入SpringApplication构造器还是进入run()方法,IDEA会把他们以紫色标出,由于这里我们分析SpringApplication创建,所以我们选择进入SpringApplication构造器,点机SpringApplication,来到了这,调用this构造器
接着stepinto,来到了SpringApplication构造器,我们一步步stepout,跳过类的变量初始化,这是个赋初始默认值的过程
最后终于进入了SpringApplication构造器当中的第一行代码

this.primarySources
在SpringApplication构造器方法当中stepout到这,this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
给主资源this.primarySources赋值,就是我们的主类class com.atguigu.boot.Boot09HelloTestApplication
this.webApplicationType
接下来我们stepinto进this.webApplicationType = WebApplicationType.deduceFromClasspath();看看做了什么事情
使用ClassUtils工具类,会先判断我们的应用是响应式reactive吗org.springframework.web.reactive.DispatcherHandler,发现不是
我们的应用是servlet的,所以最终会返回return WebApplicationType.SERVLET;
一行行stepout,我们最终跳出static WebApplicationType deduceFromClasspath() {}方法,返回到上一级,
发现SpringApplication构造器中的this.webApplicationType终于赋到了值,为SERVLET
this.bootstrappers
下面我们stepout,this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
给初始启动引导器(List
setInitializers
下面我们stepout,setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));会去找 ApplicationContextInitializer;
去spring.factories找 ApplicationContextInitializer,最终赋值给SpringApplication类的变量,,this.initializers,size=8
List<ApplicationContextInitializer<?>> initializers.size=8

debug栏的this代表当前SpringApplication构造器,展开this,会印证this.initializers.size=8
关于
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));具体做了什么事呢? stepinto看看




发现它还是从"META-INF/spring.factories"加载所谓的ApplicationContextInitializer
发现spring-boot-2.4.0.jar下有5个Initializer
# Application Context Initializersorg.springframework.context.ApplicationContextInitializer=\org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\org.springframework.boot.context.ContextIdApplicationContextInitializer,\org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,\org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
发现spring-boot-autoconfigure-2.3.4.RELEASE.jar下有2个Initializer
# Initializersorg.springframework.context.ApplicationContextInitializer=\org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
加起来一共7个ApplicationContextInitializer
setListeners
接着stepout,setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
会去找ApplicationListener ;应用监听器。去spring.factories找 ApplicationListener,赋值给SpringApplication类的变量this.listeners,size=10
private List<ApplicationListener<?>> listeners;


同理,发现它还是从"META-INF/spring.factories"加载所谓的ApplicationListener ;应用监听器
发现spring-boot-2.4.0.jar下有9个ApplicationListener
# Application Listenersorg.springframework.context.ApplicationListener=\org.springframework.boot.ClearCachesApplicationListener,\org.springframework.boot.builder.ParentContextCloserApplicationListener,\org.springframework.boot.context.FileEncodingApplicationListener,\org.springframework.boot.context.config.AnsiOutputApplicationListener,\org.springframework.boot.context.config.DelegatingApplicationListener,\org.springframework.boot.context.logging.LoggingApplicationListener,\org.springframework.boot.env.EnvironmentPostProcessorApplicationListener,\org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
发现spring-boot-autoconfigure-2.3.4.RELEASE.jar下有1个ApplicationListener
# Application Listenersorg.springframework.context.ApplicationListener=\org.springframework.boot.autoconfigure.BackgroundPreinitializer
加起来一共10个ApplicationContextInitializer
this.mainApplicationClass
接着stepout,this.mainApplicationClass = deduceMainApplicationClass();,找我们的主程序,我们stepinto看看deduceMainApplicationClass()的大概逻辑:找到第一个带有main方法的程序,就是我们的主程序

stepout结束返回:
stepout结束再返回:
stepout结束再返回:
到这里,再stepinto就轮到run()方法啦,即运行SpringApplication的分析啦,我们下期再见!
