概览如果你对Spring Boot 启动流程还不甚了解可阅读《Spring Boot 启动流程详解》这篇文章。如果你已了解那就让我们直接看看prepareContext() 源码。private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //将环境对象放到上下文中 context.setEnvironment(environment); //后置处理应用上下文 postProcessApplicationContext(context); //应用初始化上下文 applyInitializers(context); //触发监听器‘上下文准备完成’时间 listeners.contextPrepared(context); //打印启动信息和激活的profile if (this.logStartupInfo) { logStartupInfo(context.getParent() null); logStartupProfileInfo(context); } // Add boot specific singleton beans //将 applicationArguments 和 printedBanner 实例注册到bean工厂 ConfigurableListableBeanFactory beanFactory context.getBeanFactory(); beanFactory.registerSingleton(springApplicationArguments, applicationArguments); if (printedBanner ! null) { beanFactory.registerSingleton(springBootBanner, printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } //是否设置bean懒加载 if (this.lazyInitialization) { //是则beanFactory后置处理添加LazyInitializationBeanFactoryPostProcessor实例 context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources SetObject sources getAllSources(); Assert.notEmpty(sources, Sources must not be empty); //加载sources load(context, sources.toArray(new Object[0])); //触发监听器‘上下文加载完毕’事件 listeners.contextLoaded(context); }通过上面的源码我们可以看出在准备上下文阶段spring boot 做了很多事情这其中主要包括以下内容postProcessApplicationContext()后置处理应用上下文。applyInitializers()‘应用’初始化上下文。listeners.contextPrepared()触发监听器的‘应用上下文准备完成’事件。懒加载模式为 beanFactory 添加 LazyInitializationBeanFactoryPostProcessor() 后置处理器。加载sources包含 primarySources 和自定义的 sources。listeners.contextLoaded()触发监听器的‘上下文加载完成’事件。接下来让我们详细的看看每个步骤具体做了什么。后置处理应用上下文postProcessApplicationContext() 上下文的后置处理这里由于 beanNameGenerator 和 resourceLoader 都为nulladdConversionService 为true故仅对bean工厂设置了 conversionService 转换服务。这里的转换服务为 ApplicationConversionService 类的单例实例。bean工厂为 GenericApplicationContext 无参构造函数创建的 DefaultListableBeanFactory()。protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator ! null) { context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader ! null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance()); } }‘应用’初始化器SuppressWarnings({ rawtypes, unchecked }) protected void applyInitializers(ConfigurableApplicationContext context) { for (ApplicationContextInitializer initializer : getInitializers()) { Class? requiredType GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context, Unable to call initializer.); initializer.initialize(context); } }applyInitializers()主要是执行SpringApplication对象实例化阶段从spring.factories配置文件中读取并加载的ApplicationContextInitializer接口实现类的initialize()方法。从方法的注释上看主要是在上下文刷新之前做一些操作。spring-boot-x.x.x.jar 默认的spring.factories中包含以下这些实现类DelegatingApplicationContextInitializer执行一些其他的ApplicationContextInitializer这些ApplicationContextInitializer来源于context.initializer.classes属性配置相当一些自定义的初始化器委托给DelegatingApplicationContextInitializer执行ContextIdApplicationContextInitializer构建一个上下文ContextId对象并注册到bean工厂中这里的id一般为从environment环境对象中读取的spring.application.name属性配置因此一般就是你设置的项目名ConfigurationWarningsApplicationContextInitializer添加一个ConfigurationWarningsPostProcessor后置处理器到bean工厂后置处理器中该后置处理器主要校验ComponentScan扫描的包或类所在包是否包含org.springframework或org包含则进行warning级别的提示RSocketPortInfoApplicationContextInitializer将上下文对象包装成一个listener监听器添加到当前应用上下文的applicationListeners监听器列表中包装的listener主要监听了RSocketServerInitializedEvent事件将获取的端口设置到类型名为server.ports的属性map中key为local.rsocket.server.portServerPortInfoApplicationContextInitializer将自身添加到当前应用上下文的applicationListeners监听器列表中ServerPortInfoApplicationContextInitializer本身也实现的ApplicationListener接口主要监听了WebServerInitializedEvent事件以上表格的ApplicationContextInitializer都是按优先级排过序的程序执行时就是从上到下执行。另外实际断点的过程中我们可以看到除了以上的initializer之外还有一些其他jar包中的initializer如下org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer将CachingMetadataReaderFactoryPostProcessor添加到上下文对象的beanFactoryPostProcessors列表中io.dubbo.springboot.DubboConfigurationApplicationContextInitializerenvironment环境中是否设置spring.dubbo.scan属性如果设置了则实例化一个AnnotationBean并注册到bean工厂中同时添加到上下文对象的bean工厂后置处理器列表中和beanFactory对象的bean后置处理器列表中。org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener构建一个ConditionEvaluationReportListener监听器并添加到当前应用上下文的applicationListeners监听器列表中同时从bean工厂中获取ConditionEvaluationReport。ConditionEvaluationReportListener监听所有的ApplicationEvent事件并触发ConditionEvaluationReportLoggingListener的onApplicationEvent()方法。主要目的打印条件评估报告以帮助开发者了解Spring Boot 启动过程中自动配置的细节。实际执行顺序如下图所示这里解释下GenericTypeResolver.resolveTypeArgumen() 方法作用其主要是解析initializer类实现泛型接口的泛型类型从而判断当前context是否是initializer类实现接口的泛型类型的子类。这里有点绕口大家可以理解为 ApplicationContextInitializer 接口的泛型类型必须和context接口类型一致代码上看ApplicationContextInitializer接口的泛型类型就是ConfigurableApplicationContext 类型所以感觉这里的判断有点多此一举。触发监听器‘上下文准备完成’事件listeners.contextPrepared() 表示在上下文准备完成阶段要触发的操作。该事件触发的流程与listeners.starting() 执行流程一致这里不再讲解如不清楚可先看看《Spring Boot 启动流程详解》这篇文章。通过打断点可以看到这里监听了 ApplicationContextInitializedEvent 事件的监听器有BackgroundPreinitializer、DelegatingApplicationListener、DubboHolderListener实际这三个listener 都未有 ApplicationContextInitializedEvent 事件的处理逻辑这里之所有会被扫描出来是因为其实现的接口泛型类型为 ApplicationContextInitializedEvent 的父类或者未指定其中 DubboHolderListener 属于未指定。打印启动信息和激活的profile上面表格之所以没有列这一步是因为这里只是打印启动信息及激活profile没有这一步骤对框架执行并不影响所以也不重要。注册 ApplicationArguments 和 Banner bean设置bean是否可以被覆盖这里通过 DefaultListableBeanFactory 将 ApplicationArguments 和 Banner 实例对象以单例的方式进行注入同时设置不允许 bean 被覆盖让我们看看 registerSingleton() 方法源码Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { //调用父类DefaultSingletonBeanRegistry的registerSingleton() 方法 super.registerSingleton(beanName, singletonObject); //更新工厂内部维护的单例bean名称 updateManualSingletonNames(set - set.add(beanName), set - !this.beanDefinitionMap.containsKey(beanName)); //清除映射 clearByTypeCache(); }源码很简单调用父类的 DefaultSingletonBeanRegistry 的 registerSingleton() 方法让我再看看 DefaultSingletonBeanRegistry 类的 registerSingleton() 方法。Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, Bean name must not be null); Assert.notNull(singletonObject, Singleton object must not be null); synchronized (this.singletonObjects) { Object oldObject this.singletonObjects.get(beanName); if (oldObject ! null) { throw new IllegalStateException(Could not register object [ singletonObject ] under bean name beanName : there is already object [ oldObject ] bound); } addSingleton(beanName, singletonObject); } } protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }其逻辑也很简单就是先加锁再判断内部维度单例bean的map是否包含当前bean包含则抛出异常单例bean不能被重复创建。如果不存在则加到缓存map中。加载sources先看看源码~protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug(Loading source StringUtils.arrayToCommaDelimitedString(sources)); } //创建一个BeanDefinitionLoader用于加载bean BeanDefinitionLoader loader createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator ! null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader ! null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment ! null) { loader.setEnvironment(this.environment); } //进行bean的装载 loader.load(); }getBeanDefinitionRegistry() 方法用于从上下文中获取bean工厂断点可以看到返回的是context自身因为其实现了BeanDefinitionRegistry接口。createBeanDefinitionLoader() 方法就是调用 BeanDefinitionLoader() 的构造函数函数入参包含当前上下文context 和 sources这里sources主要就是 primarySources而 primarySources 就是Spring Boot 启动类。让我们再看看 BeanDefinitionLoader() 构造函数。BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, Registry must not be null); Assert.notEmpty(sources, Sources must not be empty); this.sources sources; //创建注解bean定义reader this.annotatedReader new AnnotatedBeanDefinitionReader(registry); //创建xml bean定义reader this.xmlReader new XmlBeanDefinitionReader(registry); if (isGroovyPresent()) { //如果有加载groovy.lang.MetaClass在创建groovy定义bean的reader this.groovyReader new GroovyBeanDefinitionReader(registry); } //创建类路径bean定义扫描器 this.scanner new ClassPathBeanDefinitionScanner(registry); //添加类排除过滤器 this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); }BeanDefinitionLoader 构造函数主要就是创建各种bean定义解析器用于bean的定义加载。接下来就是调用创建好的 BeanDefinitionLoader 的 load() 方法其主要作用就是加载定义的bean包括注解定义、xml定义、groovy脚本定义以及classPath定义。由于这部分实现比较复杂这里不做详细说明后面会单独写一篇文章进行详细介绍。触发监听器‘上下文加载完成’事件一样的事件处理流程就不再多说了这里主要看看执行了哪些listener的相应事件。同样断点可以看到有如下监听器监听了 ApplicationPreparedEvent 事件这里也通过表格展示下每个监听器具体干了什么。CloudFoundryVcapEnvironmentPostProcessor从内部定义的延迟日志DeferredLog切换到实时日志并进行打印ConfigFileApplicationListener添加一个属性源后置处理 PropertySourceOrderingPostProcessor 到bean工厂后置处理器列表中LoggingApplicationListener注册springBootLoggingSystem、springBootLogFile、springBootLoggerGroups等相关beanBackgroundPreinitializer无响应的事件处理DelegatingApplicationListener无响应的事件处理DubboHolderListenerspring-boot-dubbo-starter-1.0.0.jar中的监听器内部啥也没干。。。至此spring boot 在启动时的上下文准备阶段主要就干了这些事。注spring boot 版本为2.3.10
Spring Boot 项目启动时在 prepareContext 阶段做了哪些事?
发布时间:2026/7/15 16:00:21
概览如果你对Spring Boot 启动流程还不甚了解可阅读《Spring Boot 启动流程详解》这篇文章。如果你已了解那就让我们直接看看prepareContext() 源码。private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) { //将环境对象放到上下文中 context.setEnvironment(environment); //后置处理应用上下文 postProcessApplicationContext(context); //应用初始化上下文 applyInitializers(context); //触发监听器‘上下文准备完成’时间 listeners.contextPrepared(context); //打印启动信息和激活的profile if (this.logStartupInfo) { logStartupInfo(context.getParent() null); logStartupProfileInfo(context); } // Add boot specific singleton beans //将 applicationArguments 和 printedBanner 实例注册到bean工厂 ConfigurableListableBeanFactory beanFactory context.getBeanFactory(); beanFactory.registerSingleton(springApplicationArguments, applicationArguments); if (printedBanner ! null) { beanFactory.registerSingleton(springBootBanner, printedBanner); } if (beanFactory instanceof DefaultListableBeanFactory) { ((DefaultListableBeanFactory) beanFactory) .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding); } //是否设置bean懒加载 if (this.lazyInitialization) { //是则beanFactory后置处理添加LazyInitializationBeanFactoryPostProcessor实例 context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor()); } // Load the sources SetObject sources getAllSources(); Assert.notEmpty(sources, Sources must not be empty); //加载sources load(context, sources.toArray(new Object[0])); //触发监听器‘上下文加载完毕’事件 listeners.contextLoaded(context); }通过上面的源码我们可以看出在准备上下文阶段spring boot 做了很多事情这其中主要包括以下内容postProcessApplicationContext()后置处理应用上下文。applyInitializers()‘应用’初始化上下文。listeners.contextPrepared()触发监听器的‘应用上下文准备完成’事件。懒加载模式为 beanFactory 添加 LazyInitializationBeanFactoryPostProcessor() 后置处理器。加载sources包含 primarySources 和自定义的 sources。listeners.contextLoaded()触发监听器的‘上下文加载完成’事件。接下来让我们详细的看看每个步骤具体做了什么。后置处理应用上下文postProcessApplicationContext() 上下文的后置处理这里由于 beanNameGenerator 和 resourceLoader 都为nulladdConversionService 为true故仅对bean工厂设置了 conversionService 转换服务。这里的转换服务为 ApplicationConversionService 类的单例实例。bean工厂为 GenericApplicationContext 无参构造函数创建的 DefaultListableBeanFactory()。protected void postProcessApplicationContext(ConfigurableApplicationContext context) { if (this.beanNameGenerator ! null) { context.getBeanFactory().registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, this.beanNameGenerator); } if (this.resourceLoader ! null) { if (context instanceof GenericApplicationContext) { ((GenericApplicationContext) context).setResourceLoader(this.resourceLoader); } if (context instanceof DefaultResourceLoader) { ((DefaultResourceLoader) context).setClassLoader(this.resourceLoader.getClassLoader()); } } if (this.addConversionService) { context.getBeanFactory().setConversionService(ApplicationConversionService.getSharedInstance()); } }‘应用’初始化器SuppressWarnings({ rawtypes, unchecked }) protected void applyInitializers(ConfigurableApplicationContext context) { for (ApplicationContextInitializer initializer : getInitializers()) { Class? requiredType GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context, Unable to call initializer.); initializer.initialize(context); } }applyInitializers()主要是执行SpringApplication对象实例化阶段从spring.factories配置文件中读取并加载的ApplicationContextInitializer接口实现类的initialize()方法。从方法的注释上看主要是在上下文刷新之前做一些操作。spring-boot-x.x.x.jar 默认的spring.factories中包含以下这些实现类DelegatingApplicationContextInitializer执行一些其他的ApplicationContextInitializer这些ApplicationContextInitializer来源于context.initializer.classes属性配置相当一些自定义的初始化器委托给DelegatingApplicationContextInitializer执行ContextIdApplicationContextInitializer构建一个上下文ContextId对象并注册到bean工厂中这里的id一般为从environment环境对象中读取的spring.application.name属性配置因此一般就是你设置的项目名ConfigurationWarningsApplicationContextInitializer添加一个ConfigurationWarningsPostProcessor后置处理器到bean工厂后置处理器中该后置处理器主要校验ComponentScan扫描的包或类所在包是否包含org.springframework或org包含则进行warning级别的提示RSocketPortInfoApplicationContextInitializer将上下文对象包装成一个listener监听器添加到当前应用上下文的applicationListeners监听器列表中包装的listener主要监听了RSocketServerInitializedEvent事件将获取的端口设置到类型名为server.ports的属性map中key为local.rsocket.server.portServerPortInfoApplicationContextInitializer将自身添加到当前应用上下文的applicationListeners监听器列表中ServerPortInfoApplicationContextInitializer本身也实现的ApplicationListener接口主要监听了WebServerInitializedEvent事件以上表格的ApplicationContextInitializer都是按优先级排过序的程序执行时就是从上到下执行。另外实际断点的过程中我们可以看到除了以上的initializer之外还有一些其他jar包中的initializer如下org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer将CachingMetadataReaderFactoryPostProcessor添加到上下文对象的beanFactoryPostProcessors列表中io.dubbo.springboot.DubboConfigurationApplicationContextInitializerenvironment环境中是否设置spring.dubbo.scan属性如果设置了则实例化一个AnnotationBean并注册到bean工厂中同时添加到上下文对象的bean工厂后置处理器列表中和beanFactory对象的bean后置处理器列表中。org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener构建一个ConditionEvaluationReportListener监听器并添加到当前应用上下文的applicationListeners监听器列表中同时从bean工厂中获取ConditionEvaluationReport。ConditionEvaluationReportListener监听所有的ApplicationEvent事件并触发ConditionEvaluationReportLoggingListener的onApplicationEvent()方法。主要目的打印条件评估报告以帮助开发者了解Spring Boot 启动过程中自动配置的细节。实际执行顺序如下图所示这里解释下GenericTypeResolver.resolveTypeArgumen() 方法作用其主要是解析initializer类实现泛型接口的泛型类型从而判断当前context是否是initializer类实现接口的泛型类型的子类。这里有点绕口大家可以理解为 ApplicationContextInitializer 接口的泛型类型必须和context接口类型一致代码上看ApplicationContextInitializer接口的泛型类型就是ConfigurableApplicationContext 类型所以感觉这里的判断有点多此一举。触发监听器‘上下文准备完成’事件listeners.contextPrepared() 表示在上下文准备完成阶段要触发的操作。该事件触发的流程与listeners.starting() 执行流程一致这里不再讲解如不清楚可先看看《Spring Boot 启动流程详解》这篇文章。通过打断点可以看到这里监听了 ApplicationContextInitializedEvent 事件的监听器有BackgroundPreinitializer、DelegatingApplicationListener、DubboHolderListener实际这三个listener 都未有 ApplicationContextInitializedEvent 事件的处理逻辑这里之所有会被扫描出来是因为其实现的接口泛型类型为 ApplicationContextInitializedEvent 的父类或者未指定其中 DubboHolderListener 属于未指定。打印启动信息和激活的profile上面表格之所以没有列这一步是因为这里只是打印启动信息及激活profile没有这一步骤对框架执行并不影响所以也不重要。注册 ApplicationArguments 和 Banner bean设置bean是否可以被覆盖这里通过 DefaultListableBeanFactory 将 ApplicationArguments 和 Banner 实例对象以单例的方式进行注入同时设置不允许 bean 被覆盖让我们看看 registerSingleton() 方法源码Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { //调用父类DefaultSingletonBeanRegistry的registerSingleton() 方法 super.registerSingleton(beanName, singletonObject); //更新工厂内部维护的单例bean名称 updateManualSingletonNames(set - set.add(beanName), set - !this.beanDefinitionMap.containsKey(beanName)); //清除映射 clearByTypeCache(); }源码很简单调用父类的 DefaultSingletonBeanRegistry 的 registerSingleton() 方法让我再看看 DefaultSingletonBeanRegistry 类的 registerSingleton() 方法。Override public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException { Assert.notNull(beanName, Bean name must not be null); Assert.notNull(singletonObject, Singleton object must not be null); synchronized (this.singletonObjects) { Object oldObject this.singletonObjects.get(beanName); if (oldObject ! null) { throw new IllegalStateException(Could not register object [ singletonObject ] under bean name beanName : there is already object [ oldObject ] bound); } addSingleton(beanName, singletonObject); } } protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }其逻辑也很简单就是先加锁再判断内部维度单例bean的map是否包含当前bean包含则抛出异常单例bean不能被重复创建。如果不存在则加到缓存map中。加载sources先看看源码~protected void load(ApplicationContext context, Object[] sources) { if (logger.isDebugEnabled()) { logger.debug(Loading source StringUtils.arrayToCommaDelimitedString(sources)); } //创建一个BeanDefinitionLoader用于加载bean BeanDefinitionLoader loader createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources); if (this.beanNameGenerator ! null) { loader.setBeanNameGenerator(this.beanNameGenerator); } if (this.resourceLoader ! null) { loader.setResourceLoader(this.resourceLoader); } if (this.environment ! null) { loader.setEnvironment(this.environment); } //进行bean的装载 loader.load(); }getBeanDefinitionRegistry() 方法用于从上下文中获取bean工厂断点可以看到返回的是context自身因为其实现了BeanDefinitionRegistry接口。createBeanDefinitionLoader() 方法就是调用 BeanDefinitionLoader() 的构造函数函数入参包含当前上下文context 和 sources这里sources主要就是 primarySources而 primarySources 就是Spring Boot 启动类。让我们再看看 BeanDefinitionLoader() 构造函数。BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { Assert.notNull(registry, Registry must not be null); Assert.notEmpty(sources, Sources must not be empty); this.sources sources; //创建注解bean定义reader this.annotatedReader new AnnotatedBeanDefinitionReader(registry); //创建xml bean定义reader this.xmlReader new XmlBeanDefinitionReader(registry); if (isGroovyPresent()) { //如果有加载groovy.lang.MetaClass在创建groovy定义bean的reader this.groovyReader new GroovyBeanDefinitionReader(registry); } //创建类路径bean定义扫描器 this.scanner new ClassPathBeanDefinitionScanner(registry); //添加类排除过滤器 this.scanner.addExcludeFilter(new ClassExcludeFilter(sources)); }BeanDefinitionLoader 构造函数主要就是创建各种bean定义解析器用于bean的定义加载。接下来就是调用创建好的 BeanDefinitionLoader 的 load() 方法其主要作用就是加载定义的bean包括注解定义、xml定义、groovy脚本定义以及classPath定义。由于这部分实现比较复杂这里不做详细说明后面会单独写一篇文章进行详细介绍。触发监听器‘上下文加载完成’事件一样的事件处理流程就不再多说了这里主要看看执行了哪些listener的相应事件。同样断点可以看到有如下监听器监听了 ApplicationPreparedEvent 事件这里也通过表格展示下每个监听器具体干了什么。CloudFoundryVcapEnvironmentPostProcessor从内部定义的延迟日志DeferredLog切换到实时日志并进行打印ConfigFileApplicationListener添加一个属性源后置处理 PropertySourceOrderingPostProcessor 到bean工厂后置处理器列表中LoggingApplicationListener注册springBootLoggingSystem、springBootLogFile、springBootLoggerGroups等相关beanBackgroundPreinitializer无响应的事件处理DelegatingApplicationListener无响应的事件处理DubboHolderListenerspring-boot-dubbo-starter-1.0.0.jar中的监听器内部啥也没干。。。至此spring boot 在启动时的上下文准备阶段主要就干了这些事。注spring boot 版本为2.3.10