SpringApplication方法run的事件监听器机制

本文详细解析了SpringBoot启动过程中的事件监听机制,包括SpringApplicationRunListeners如何收集和通知SpringApplicationRunListener实例,以及这些监听器如何在不同阶段触发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

Spring boot应用,这里具体的来说,是指类SpringApplication,在其run()方法运行过程中,主要围绕所使用ApplicationContext对象的生命周期事件,应用了一个事件监听器机制提供了相应的程序扩展入口点,开发人员可以基于此机制,在相应的事件发生时执行特定的逻辑。

SpringApplication应用的该事件监听器机制主要利用如下两个类/接口 :

  1. SpringApplicationRunListeners
  2. SpringApplicationRunListener

简单来讲,在SpringApplication的run()方法执行时,应用上下文ApplicationContext对象创建之前,应用程序会首先找到配置中所定义的所有SpringApplicationRunListener的实现类(这些实现类可能由Spring boot自身实现和提供,也可以由开发人员来实现和提供),创建他们的实例,然后把它们放在一个集合中,然后封装为一个 SpringApplicationRunListeners 实例。之后Spring boot应用开始创建ApplicationContext对象,然后在相应的ApplicationContext的生命周期事件发生时,程序会通过该SpringApplicationRunListeners 实例向各个 SpringApplicationRunListener 实例广播相应的事件,从而SpringApplicationRunListener 实现类中相应的监听器逻辑得到执行。

这里所提到的SpringApplicationContext的生命周期事件,具体来讲,是如下事件 :

发生顺序事件简介
1environmentPrepared环境已经准备好,但是ApplicationContext实例尚未被创建
2contextPreparedApplicationContext已经被创建并且准备就绪,但是sources尚未被加载
3contextLoadedApplicationContext实例的sources已经被加载,但是ApplicationContext实例尚未被刷新(refresh)
4finishedSpring应用程序启动完成时发送该事件,此时ApplicationContext实例已经成功创建完成,或者遇到异常创建失败。对于该ApplicationContext是一个WebApplicationContext的情况,此时内置的Web容器已经在其他线程启动处于服务就绪状态,而SpringApplication执行主线程已经完成自己的任务。

源代码分析

SpringApplication.run()方法中事件监听有关逻辑

// SpringApplication 类
public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	ConfigurableApplicationContext context = null;
	FailureAnalyzers analyzers = null;
	configureHeadlessProperty();
	// 从配置中获取SpringApplicationRunListener实现类并实例化,
	// 最终把所有这些实例包装到一个SpringApplicationRunListeners实例来使用
	SpringApplicationRunListeners listeners = getRunListeners(args);
	// 启动各个SpringApplicationRunListener 监听器实例 
	listeners.starting();
	try {
		ApplicationArguments applicationArguments = 
					new DefaultApplicationArguments(args);
		// 准备环境
		// 结束时会向各个SpringApplicationRunListener发送事件 
		// environmentPrepared					
		ConfigurableEnvironment environment = 
					prepareEnvironment(listeners,applicationArguments);
		Banner printedBanner = printBanner(environment);
		context = createApplicationContext();// 这里创建应用上下文
		analyzers = new FailureAnalyzers(context);
		// 准备应用上下文,
		// 完成时会向各个SpringApplicationRunListener发送事件 
		// contextPrepared
		prepareContext(context, environment, listeners, 
					applicationArguments,printedBanner);
		refreshContext(context);
		afterRefresh(context, applicationArguments);
		// 应用上下文准备完成
		// 向各个SpringApplicationRunListener发送事件 
		// finished
		listeners.finished(context, null);
		stopWatch.stop();
		if (this.logStartupInfo) {
			new StartupInfoLogger(this.mainApplicationClass)
					.logStarted(getApplicationLog(), stopWatch);
		}
		return context;
	}
	catch (Throwable ex) {
		// 应用上下文准备遇到异常时,
		// 向各个SpringApplicationRunListener发送事件finished,
		// 携带响应异常信息
		handleRunFailure(context, listeners, analyzers, ex);
		throw new IllegalStateException(ex);
	}
}

SpringApplicationRunListener实例来自哪里?

上面对SpringApplication.run()的分析中我们提到"从配置中获取SpringApplicationRunListener实现类"并实例化,这里我们来看这些实现类具体在哪里配置,是怎样被获取的。

从上面提到的SpringApplication.getRunListeners()方法开始 :

private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
	// 1.创建一个实例SpringApplicationRunListeners,
	//   关于类(SpringApplicationRunListeners下面会有介绍)
	// 2.使用方法getSpringFactoriesInstances()获取配置中
	//   接口SpringApplicationRunListener实现的实例
	return new SpringApplicationRunListeners(logger, 
		getSpringFactoriesInstances(SpringApplicationRunListener.class, 
									types, this, args));
}

接下来我们看方法getSpringFactoriesInstances具体都做了些什么 :

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
		Class<?>[] parameterTypes, Object... args) {
	ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	// Use names and ensure unique to protect against duplicates
	Set<String> names = new LinkedHashSet<String>(
	//使用工具SpringFactoriesLoader.loadFactoryNames获取指定类type的全限定名,
	//而针对本文的情况,这里类type其实就是接口SpringApplicationRunListener
			SpringFactoriesLoader.loadFactoryNames(type, classLoader));
	// 实例化这些加载到的类
	// 针对本文的情况,在缺省配置Spring boot应用中,获取到的类是
	// org.springframework.boot.context.event.EventPublishingRunListener,
	// 这里创建该类的一个实例		
	List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
			classLoader, args, names);
	AnnotationAwareOrderComparator.sort(instances);
	return instances;
}

org.springframework.boot.context.event.EventPublishingRunListener其是存在于配置文件中:

# spring-boot-1.x.x.RELEASE.jar!\META-INF\spring.factories 配置文件片段
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

上面分析中还提到了工具类SpringFactoriesLoader,关于它可以参考这篇文章,感兴趣的话可以看看。

SpringApplicationRunListeners介绍

该类主要是将一组SpringApplicationRunListener聚合到一起,然后使用统一的方式传播事件。

其实现逻辑如下,主要就是将事件传播到各个SpringApplicationRunListener实例。

package org.springframework.boot;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.commons.logging.Log;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ReflectionUtils;

/**
 * A collection of SpringApplicationRunListener.
 *
 * @author Phillip Webb
 */
class SpringApplicationRunListeners {

	private final Log log;

	private final List<SpringApplicationRunListener> listeners;

	SpringApplicationRunListeners(Log log,
			Collection<? extends SpringApplicationRunListener> listeners) {
		this.log = log;
		this.listeners = new ArrayList<SpringApplicationRunListener>(listeners);
	}

	public void starting() {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.starting();
		}
	}

	public void environmentPrepared(ConfigurableEnvironment environment) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.environmentPrepared(environment);
		}
	}

	public void contextPrepared(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.contextPrepared(context);
		}
	}

	public void contextLoaded(ConfigurableApplicationContext context) {
		for (SpringApplicationRunListener listener : this.listeners) {
			listener.contextLoaded(context);
		}
	}

	public void finished(ConfigurableApplicationContext context, Throwable exception) {
		for (SpringApplicationRunListener listener : this.listeners) {
			callFinishedListener(listener, context, exception);
		}
	}

	private void callFinishedListener(SpringApplicationRunListener listener,
			ConfigurableApplicationContext context, Throwable exception) {
		try {
			listener.finished(context, exception);
		}
		catch (Throwable ex) {
			if (exception == null) {
				ReflectionUtils.rethrowRuntimeException(ex);
			}
			if (this.log.isDebugEnabled()) {
				this.log.error("Error handling failed", ex);
			}
			else {
				String message = ex.getMessage();
				message = (message == null ? "no error message" : message);
				this.log.warn("Error handling failed (" + message + ")");
			}
		}
	}

}

接口SpringApplicationRunListener介绍

package org.springframework.boot;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.support.SpringFactoriesLoader;

/**
 * SpringApplication run 方法的事件监听器
 * SpringApplicationRunListeners are loaded via the SpringFactoriesLoader
 * and should declare a public constructor that accepts a SpringApplication
 * instance and a String[] of arguments. A new
 * SpringApplicationRunListener instance will be created for each run.
 *
 */
public interface SpringApplicationRunListener {

	/**
	 * Called immediately when the run method has first started. Can be used for very
	 * early initialization.
	 */
	void starting();

	/**
	 * Called once the environment has been prepared, but before the
	 * ApplicationContext has been created.
	 * 环境对象准备好后,应用上下文创建前触发该事件
	 * @param environment the environment
	 */
	void environmentPrepared(ConfigurableEnvironment environment);

	/**
	 * Called once the ApplicationContext has been created and prepared, but
	 * before sources have been loaded.
	 * 应用上下文创建和准备好后,尚未加载sources之前触发该事件
	 * @param context the application context
	 */
	void contextPrepared(ConfigurableApplicationContext context);

	/**
	 * Called once the application context has been loaded but before it has been
	 * refreshed.
	 * 应用上下文加载sources后,执行refresh之前触发该事件
	 * @param context the application context
	 */
	void contextLoaded(ConfigurableApplicationContext context);

	/**
	 * Called immediately before the run method finishes.
	 * 
	 * SpringApplication 的run方法已经完成自己的任务即将结束之前触发该事件。
	 * SpringApplication 的run方法即将结束并不代表程序即将退出,只表示run方法任务的完成
	 * (成功完成或者失败完成)和方法的退出。
	 * 该事件触发时,应用上下文ApplicationContext要么已经创建成功要么已经创建失败,
	 * 并且如果是Web应用的情况下,此时Web应用应该已经处于伺服状态(此时应该是存在于其他线程中),
	 * 而整个进程并不会退出,而当前SpringApplication.run()即将退出。
	 * @param context the application context or null if a failure occurred before the
	 * context was created
	 * @param exception any run exception or null if run completed successfully.
	 */
	void finished(ConfigurableApplicationContext context, Throwable exception);

}

EventPublishingRunListener

package org.springframework.boot.context.event;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.util.ErrorHandler;

/**
 * 接口SpringApplicationRunListener的实现类,用于发布各种SpringApplicationEvent事件。
 * SpringApplicationEvent事件也是ApplicationEvent事件,但主要是跟踪SpringApplication运行。
 * 
 * 内部使用一个 ApplicationEventMulticaster 实例用于在应用上下文真正被刷新前发布各种事件。
 * ApplicationEventMulticaster 实例会管理多个ApplicationListener对象并向它们发布事件。
 * 一般应用上下文的事件发布并不是自身直接发布给监听器,而是委托给ApplicationEventMulticaster
 * 发布这些事件。 
 * 
 * @author Phillip Webb
 * @author Stephane Nicoll
 */
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
	// 所属SpringApplication对象
	private final SpringApplication application;
	// 运行参数
	private final String[] args;
	// 真正用于发布事件所使用的 ApplicationEventMulticaster ,
	// 其实是一个 SimpleApplicationEventMulticaster
	private final SimpleApplicationEventMulticaster initialMulticaster;

	public EventPublishingRunListener(SpringApplication application, String[] args) {
		this.application = application;
		this.args = args;
		this.initialMulticaster = new SimpleApplicationEventMulticaster();
		// 从appliction中获取已经根据配置实例化的各个ApplicationListener,
		// 将它们设置到事件多播器,随后的各种事件发布通过该事件多播器向这些
		// ApplicationListener发布
		for (ApplicationListener<?> listener : application.getListeners()) {
			this.initialMulticaster.addApplicationListener(listener);
		}
	}

	@Override
	public int getOrder() {
		return 0;
	}

	@Override
	@SuppressWarnings("deprecation")
	public void starting() {
		// 发布事件 ApplicationStartedEvent
		this.initialMulticaster
				.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
	}

	@Override
	public void environmentPrepared(ConfigurableEnvironment environment) {
		// 发布事件 ApplicationEnvironmentPreparedEvent
		this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
				this.application, this.args, environment));
	}

	@Override
	public void contextPrepared(ConfigurableApplicationContext context) {
		
	}

	@Override
	public void contextLoaded(ConfigurableApplicationContext context) {
		// 在应用上下文已经加载但是尚未刷新前将SpringApplication对象中所加载的
		// ApplicationListener和应用上下文做关联
		for (ApplicationListener<?> listener : this.application.getListeners()) {
			if (listener instanceof ApplicationContextAware) {
				((ApplicationContextAware) listener).setApplicationContext(context);
			}
			context.addApplicationListener(listener);
		}
		// 发布事件 ApplicationPreparedEvent
		this.initialMulticaster.multicastEvent(
				new ApplicationPreparedEvent(this.application, this.args, context));
	}

	@Override
	public void finished(ConfigurableApplicationContext context, Throwable exception) {
		SpringApplicationEvent event = getFinishedEvent(context, exception);
		if (context != null && context.isActive()) {
			// 现在应用上下文存在并且活跃,而且
			// 所有的事件监听器都已经关联到应用上下文上面了,所以直接利用应用上下文发布事件
			context.publishEvent(event);
		}
		else {
			// 一个不活跃的应用上下文不一定有多播器,所以这里我们使用自己的多播器
			// initialMulticaster发布事件
			if (context instanceof AbstractApplicationContext) {
				for (ApplicationListener<?> listener : 
						((AbstractApplicationContext) context).getApplicationListeners()) {
					this.initialMulticaster.addApplicationListener(listener);
				}
			}
			if (event instanceof ApplicationFailedEvent) {
				this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
			}
			this.initialMulticaster.multicastEvent(event);
		}
	}

	// 根据上下文和异常情况判断当前是哪种应用程序启动过程结束 : 
	// 1. SpringApplication启动异常结束,一般启动异常结束也表示程序运行将要结束
	// 2. SpringApplication启动正常结束
	// 注意:启动正常结束不表示程序运行结束,相反,可能表示程序运行刚就绪开始提供服务
	private SpringApplicationEvent getFinishedEvent(
			ConfigurableApplicationContext context, Throwable exception) {
		if (exception != null) {
			return new ApplicationFailedEvent(this.application, this.args, context,
					exception);
		}
		return new ApplicationReadyEvent(this.application, this.args, context);
	}

	private static class LoggingErrorHandler implements ErrorHandler {

		private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);

		@Override
		public void handleError(Throwable throwable) {
			logger.warn("Error calling ApplicationEventListener", throwable);
		}

	}

}

从上面EventPublishingRunListener的代码可以看出 :
1.EventPublishingRunListener主要任务是被SpringApplication.run()调用,负责发布相应事件;
2. EventPublishingRunListener发布的事件的监听器是SpringApplication从配置中获取的监听器;
3. EventPublishingRunListener不仅负责发布事件,而且在合适的时机将SpringApplication所获取的监听器和应用上下文作关联。

<think>好的,我现在需要帮助用户理解从`SpringApplication.run(Application.class, args);`开始的Spring Boot启动流程。用户之前已经询问过Bean的创建、初始化和赋值的源码,现在他们可能想进一步了解整个应用的启动过程,特别是Spring Boot是如何启动并初始化应用的。 首先,我需要回忆一下Spring Boot的启动流程。记得`SpringApplication.run()`是入口方法,它会触发自动配置、上下文初始化、Bean加载等步骤。用户可能对底层机制感兴趣,比如如何加载配置、如何启动内嵌服务器,或者整个生命周期中的关键步骤。 接下来,我需要确定用户的背景。他们可能是一个开发者,正在学习Spring Boot,或者在工作中需要调试启动问题。因此,我需要详细但清晰地解释每个阶段,包括关键类和方法,同时避免过于晦涩的术语。 我需要组织回答的结构。可能按照启动流程的顺序,从创建SpringApplication实例开始,到准备环境、创建上下文、刷新上下文,最后启动内嵌服务器。每个步骤要说明做了什么,涉及哪些核心类,以及它们的作用。 还要注意用户之前的提问中提到了源码解析,所以这次回答可能需要引用具体的源码位置,比如`SpringApplication`类的构造方法、`run()`方法的具体实现,以及`AbstractApplicationContext`的`refresh()`方法。这能帮助用户更深入地理解内部机制。 另外,用户可能对自动配置的原理感兴趣,比如`@SpringBootApplication`背后的机制,如何加载`spring.factories`,以及条件注解如何工作。这部分需要简要提及,但不要过于深入,以免偏离启动流程的主线。 还需要考虑性能优化和常见问题,比如启动时的监听器、事件机制,或者如何自定义启动过程。但根据用户当前的问题,可能暂时不需要展开这些,除非用户后续有更多问题。 最后,我应该使用图表或流程图来辅助说明,比如Mermaid的流程图,帮助用户可视化整个流程。同时,代码示例和源码位置的引用能增加回答的可信度和实用性。 总结一下,回答的结构应该是: 1. 入口方法`run()`的作用和两个阶段。 2. 详细分解每个阶段,包括实例创建、环境准备、上下文创建和刷新。 3. 关键扩展点,如监听器、自动配置、Bean加载。 4. 图示和源码引用,帮助用户理解。 5. 可能的后续步骤或相关知识点,引导用户进一步学习。 需要确保语言简洁,逻辑清晰,逐步引导用户理解整个启动过程。同时,注意使用中文术语,避免直译导致的歧义。</think>以下是Spring Boot应用启动过程的核心源码解析(基于Spring Boot 2.5.x版本): --- ### 一、启动流程全景图 ```mermaid graph TD A[run()入口] --> B[创建SpringApplication实例] B --> C[执行run方法] C --> D[准备环境] D --> E[创建应用上下文] E --> F[刷新上下文] F --> G[执行Runners] ``` --- ### 二、启动源码深度解析 #### 1. 入口方法`SpringApplication.run()` **源码位置**:`SpringApplication.java` ```java public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class<?>[] { primarySource }, args); } public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); // 分两个阶段 } ``` --- ### 三、SpringApplication实例化阶段 #### 1. 构造方法核心逻辑 ```java public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { // 1. 设置主配置类 this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); // 2. 推断WEB应用类型(Servlet/Reactive) this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 3. 加载初始化器(META-INF/spring.factories) setInitializers(getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 4. 加载监听器(关键事件监听) setListeners(getSpringFactoriesInstances(ApplicationListener.class)); // 5. 推断主启动类 this.mainApplicationClass = deduceMainApplicationClass(); } ``` --- ### 四、run()方法执行阶段 #### 1. 完整执行流程 **源码位置**:`SpringApplication#run` ```java public ConfigurableApplicationContext run(String... args) { // 阶段1:启动准备 StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; configureHeadlessProperty(); // 获取运行监听器 SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); // 发送ApplicationStartingEvent try { // 阶段2:环境准备 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); // 阶段3:创建上下文 context = createApplicationContext(); // 阶段4:上下文预处理 prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 阶段5:刷新上下文(核心!) refreshContext(context); // 阶段6:后置处理 afterRefresh(context, applicationArguments); stopWatch.stop(); // 发送ApplicationReadyEvent listeners.started(context); } catch (Throwable ex) { handleRunFailure(context, ex, listeners); throw new IllegalStateException(ex); } return context; } ``` --- ### 五、关键阶段详解 #### 1. 环境准备(prepareEnvironment) ```java private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) { // 创建环境(根据WEB类型创建对应环境) ConfigurableEnvironment environment = getOrCreateEnvironment(); // 配置PropertySources和Profiles configureEnvironment(environment, applicationArguments.getSourceArgs()); // 发送EnvironmentPreparedEvent listeners.environmentPrepared(environment); // 绑定Spring Boot配置(将环境变量绑定到SpringBootApplication对象) bindToSpringApplication(environment); return environment; } ``` #### 2. 上下文创建(createApplicationContext) ```java protected ConfigurableApplicationContext createApplicationContext() { // 根据webApplicationType选择上下文类型 return this.applicationContextFactory.create(this.webApplicationType); } // 默认实现(AnnotationConfigServletWebServerApplicationContext等) static { ApplicationContextFactory DEFAULT = (webApplicationType) -> { switch (webApplicationType) { case SERVLET: return new AnnotationConfigServletWebServerApplicationContext(); case REACTIVE: return new AnnotationConfigReactiveWebServerApplicationContext(); default: return new AnnotationConfigApplicationContext(); } }; } ``` #### 3. 上下文刷新(refreshContext) **核心源码位置**:`AbstractApplicationContext#refresh` ```java public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新(记录启动时间、初始化属性源等) prepareRefresh(); // 2. 获取新的BeanFactory(重要!) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 3. BeanFactory预处理(注册环境相关的Bean) prepareBeanFactory(beanFactory); // 4. BeanFactory后处理(加载配置类、组件扫描等) postProcessBeanFactory(beanFactory); // 5. 执行BeanFactoryPostProcessor invokeBeanFactoryPostProcessors(beanFactory); // 6. 注册BeanPostProcessor registerBeanPostProcessors(beanFactory); // 7. 初始化MessageSource(国际化) initMessageSource(); // 8. 初始化事件广播器 initApplicationEventMulticaster(); // 9. 子类扩展方法(如创建Web服务器) onRefresh(); // 10. 注册监听器 registerListeners(); // 11. 完成Bean初始化(重点!实例化所有非懒加载单例Bean) finishBeanFactoryInitialization(beanFactory); // 12. 完成刷新(发布ContextRefreshedEvent) finishRefresh(); } } ``` --- ### 六、自动配置原理 #### 1. @SpringBootApplication注解 ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Configuration @EnableAutoConfiguration // 核心注解 @ComponentScan public @interface SpringBootApplication { // ... } ``` #### 2. 自动配置触发流程 ```mermaid sequenceDiagram participant A as @EnableAutoConfiguration participant B as AutoConfigurationImportSelector participant C as spring.factories participant D as @Conditional条件判断 A->>B: 选择导入配置 B->>C: 加载META-INF/spring.factories C->>B: 返回自动配置类列表 B->>D: 执行条件注解过滤 D->>B: 返回有效配置类 B->>Spring: 注册有效配置类 ``` --- ### 七、内嵌Web服务器启动 #### 1. Web服务器创建流程 ```java // ServletWebServerApplicationContext protected void onRefresh() { super.onRefresh(); try { createWebServer(); // 创建Web服务器 } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } } private void createWebServer() { // 从BeanFactory获取ServletWebServerFactory ServletWebServerFactory factory = getWebServerFactory(); // 创建WebServer(Tomcat/Jetty/Undertow) this.webServer = factory.getWebServer(getSelfInitializer()); } ``` --- ### 八、启动后扩展点 #### 1. 常用扩展接口 | 接口类型 | 执行时机 | 典型用途 | |---------------------------|----------------------------|--------------------------| | ApplicationRunner | 上下文刷新完成后 | 启动后执行初始化任务 | | CommandLineRunner | 同ApplicationRunner | 命令行参数处理 | | ApplicationListener | 监听特定事件 | 监控启动过程 | | BeanPostProcessor | Bean初始化前后 | Bean增强处理 | ```java // 示例:ApplicationRunner实现 @Component public class MyRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) { System.out.println("应用启动完成!"); } } ``` --- ### 九、性能优化建议 1. **减少组件扫描范围**: ```properties spring.component-scan.base-packages=com.example.core ``` 2. **延迟初始化**: ```java @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication app = new SpringApplication(Application.class); app.setLazyInitialization(true); // 启用全局延迟初始化 app.run(args); } } ``` 3. **排除不必要的自动配置**: ```java @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, CacheAutoConfiguration.class }) ``` --- ### 十、调试技巧 在启动时添加JVM参数: ```bash -Dlogging.level.org.springframework=DEBUG -Ddebug # 打印自动配置报告 ``` 通过这个完整的启动流程分析,可以清晰看到Spring Boot如何通过约定大于配置的原则,将复杂的Spring生态整合为简单易用的启动过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值