Spring Boot 启动原理详解
Spring Boot 的启动是一个复杂的流程,从 Main 方法开始,经过一系列步骤,最终完成 Spring 容器的初始化和应用的运行。以下是启动原理的详细解析:
1. 运行 Main 方法
- 应用程序的启动始于
Main方法的执行。 - 在
Main方法中,创建了一个SpringApplication实例,用于引导应用程序的启动。 -
关键操作:
- 加载
spring.factories文件,注册监听器、ApplicationContextInitializer等扩展接口实现。
- 加载
2. 运行 run 方法
- 调用
SpringApplication的run方法,是应用程序启动的入口。 - 在这一步中,Spring Boot 会启动 Spring 容器,同时创建内置 Tomcat。
-
关键操作:
- 读取环境变量。
- 加载配置文件(如
application.properties或application.yml)。 - 完成其他初始化工作。
3. 读取和解析配置文件
- Spring Boot 读取并解析环境变量和配置文件(如
application.properties或application.yml)。 - 获取应用程序的配置信息,用于后续初始化。
4. 创建 ApplicationContext
- 根据应用程序的类型创建相应的
ApplicationContext。- 对于 Web 应用程序,通常创建的是
ServletWebServerApplicationContext。
- 对于 Web 应用程序,通常创建的是
-
作用:
- 提供 Spring 容器,用于管理 Bean 和上下文环境。
5. 预初始化上下文
- 将启动类作为配置类,读取并注册为
BeanDefinition。 -
关键点:
- Spring 容器能够识别并处理应用程序的配置。
6. 调用 refresh 方法
- Spring Boot 调用
refresh方法加载和初始化 Spring 容器。 -
重要操作:
- 解析
@Import注解,加载自动配置类。 - 创建和注册
BeanDefinition。 - 完成 Spring 应用上下文的初始化。
- 解析
7. 创建内置 Servlet 容器
- 如果应用程序是 Web 应用程序,Spring Boot 会创建内置的 Servlet 容器(如 Tomcat)。
-
作用:
- 接收和处理 HTTP 请求。
-
特点:
- 容器自动配置,支持通过配置文件或代码自定义。
8. 调用监听器和扩展点
- 在整个启动过程中,Spring Boot 会调用监听器和扩展点:
- 监听器: 处理应用程序启动和关闭事件。
-
扩展点: 使用
ApplicationContextInitializer自定义ApplicationContext的初始化。
-
作用:
- 支持应用的扩展和定制。
9. 源码解析
Main 方法
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
SpringApplication 的构造
public SpringApplication(Class<?>... primarySources) {
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
调用 run 方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
} catch (Throwable ex) {
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
return context;
}
创建内置 Servlet 容器
protected void onRefresh() {
super.onRefresh();
try {
createWebServer();
} catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}











网友评论