Spring Boot 启动流程详解 - Launcher 类的奥秘
2022-11-29 01:05:34
深入剖析 Launcher 类:Spring Boot 启动机制的幕后英雄
Launcher 类的使命
Launcher 类 在 Spring Boot 应用程序启动过程中扮演着至关重要的角色。它负责创建一个 SpringApplication 实例,并调用其 run() 方法。run() 方法启动应用程序上下文,加载必要的 bean,并启动服务器。Launcher 类还负责处理命令行参数,允许你在启动应用程序时指定特定的配置。
Launcher 类的关键步骤
Launcher 类的启动流程包括以下关键步骤:
- 创建 SpringApplication 实例 :Launcher 类通过调用 SpringApplication.run() 方法创建 SpringApplication 实例。
- 设置应用程序的环境属性 :Launcher 类设置应用程序的环境属性,如应用程序的名称、配置文件的位置等。
- 准备应用程序上下文的运行环境 :Launcher 类准备应用程序上下文的运行环境,包括创建应用程序上下文的父上下文、设置应用程序上下文的 ClassLoader 等。
- 调用 SpringApplication 实例的 run() 方法 :Launcher 类调用 SpringApplication 实例的 run() 方法。run() 方法启动应用程序上下文,加载必要的 bean,并启动服务器。
- 加载应用程序上下文中的 bean :Launcher 类加载应用程序上下文中的 bean。bean 是 Spring 应用程序的基本构建块,它们代表应用程序中的各种组件和服务。
- 启动嵌入式服务器 :Launcher 类启动嵌入式服务器。嵌入式服务器是 Spring Boot 提供的内置服务器,它允许你无需单独部署服务器即可运行 Spring Boot 应用程序。
Launcher 类的详细介绍
1. 创建 SpringApplication 实例
Launcher 类通过调用 SpringApplication.run() 方法创建 SpringApplication 实例。该方法接收应用程序的主类和命令行参数作为参数。主类是一个包含 main() 方法的类,通常是应用程序的入口点。
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return new SpringApplication(primarySource).run(args);
}
2. 设置应用程序的环境属性
Launcher 类设置应用程序的环境属性,如应用程序的名称、配置文件的位置等。这些属性可以从命令行参数、系统属性或环境变量中获取。
protected Properties getProperties(String[] args) {
Properties properties = new Properties();
// 从命令行参数中获取属性
CommandLinePropertySource argsProps = new CommandLinePropertySource(args);
addProperties(properties, argsProps);
// 从系统属性中获取属性
SystemPropertySource systemProps = new SystemPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
addProperties(properties, systemProps);
// 从环境变量中获取属性
EnvironmentPropertySource envProps = new EnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
env);
addProperties(properties, envProps);
return properties;
}
3. 准备应用程序上下文的运行环境
Launcher 类准备应用程序上下文的运行环境,包括创建应用程序上下文的父上下文、设置应用程序上下文的 ClassLoader 等。
protected ConfigurableApplicationContext prepareContext(String[] args) {
ApplicationContext parent = createParentContext();
ConfigurableApplicationContext context = createApplicationContext();
postProcessApplicationContext(context);
// 设置应用程序上下文的父上下文
context.setParent(parent);
// 设置应用程序上下文的 ClassLoader
context.setClassLoader(getClassLoader());
return context;
}
4. 调用 SpringApplication 实例的 run() 方法
Launcher 类调用 SpringApplication 实例的 run() 方法。run() 方法启动应用程序上下文,加载必要的 bean,并启动服务器。
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[]{ClassLoader.class}, getBeanClassLoader());
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 启动应用程序上下文
ConfigurableApplicationContext parent = prepareContext(args);
context = run(parent, applicationArguments, new SimpleCommandLinePropertySource(args));
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, stopWatch);
throw new IllegalStateException(ex);
}
try {
afterRun(context, applicationArguments, stopWatch);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, stopWatch);
throw new IllegalStateException(ex);
}
return context;
}
5. 加载应用程序上下文中的 bean
Launcher 类加载应用程序上下文中的 bean。bean 是 Spring 应用程序的基本构建块,它们代表应用程序中的各种组件和服务。bean 可以通过注解、XML 配置或 Java 代码来定义。
protected ConfigurableApplicationContext run(ConfigurableApplicationContext parent, ApplicationArguments args,
PropertySource<?> propertySource) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext applicationContext;
try {
// 加载应用程序上下文中的 bean
applicationContext = refreshContext(parent, args, propertySource);
}
catch (Throwable ex) {
handleRunFailure(applicationContext, ex, getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[]{ClassLoader.class}, getBeanClassLoader()), stopWatch);
throw new IllegalStateException(ex);
}
try {
afterRefresh(applicationContext, args, stopWatch);
}
catch (Throwable ex) {
handleRunFailure(applicationContext, ex, getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[]{ClassLoader.class}, getBeanClassLoader()), stopWatch);
throw new IllegalStateException(ex);
}
return applicationContext;
}
6. 启动嵌入式服务器
Launcher 类启动嵌入式服务器。嵌入式服务器是 Spring Boot 提供的内置服务器,它允许你无需单独部署服务器即可运行 Spring Boot 应用程序。
protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args, StopWatch stopWatch) {
callRunners(context, args);
// 启动嵌入式服务器
WebServer webServer = this.webApplicationType.getWebServer(context);
webServer.start();
int port = webServer.getPort();
context.publishEvent(new ServletWebServerInitializedEvent(webServer, port, context.getServletContext()));
}
Launcher 类的实战应用
Launcher 类在 Spring Boot 应用程序中有着广泛的应用。以下是一些常见的应用场景:
- 指定应用程序的配置文件。
- 启用或禁用特定的 bean。
- 设置应用程序的端口号。
- 运行应用程序的测试用例。
总结
Launcher 类是 Spring Boot 启动流程的核心组件之一。它负责创建 SpringApplication 实例,设置应用程序的环境属性,准备应用程序上下文的运行环境,调用 SpringApplication 实例的 run() 方法,加载应用程序上下文中的 bean,并启动嵌入式服务器。通过理解 Launcher 类的启动流程,你可以更深入地理解 Spring Boot 的启动机制,并能够更加熟练地使用 Spring Boot 开发应用程序。
常见问题解答
- Launcher 类何时创建?
Launcher 类在 Spring Boot 应用程序的 main() 方法中创建。 - Launcher 类如何与 SpringApplication 类的 run() 方法交互?
Launcher 类创建 SpringApplication 实例并调用其 run() 方法来启动应用程序。 - Launcher 类如何设置应用程序的环境属性?
Launcher 类从命令行参数、系统属性和环境变量中获取应用程序的环境属性。 - Launcher 类如何准备应用程序上下文的运行环境?
Launcher 类创建应用程序上下文的父上下文、设置应用程序上下文的 ClassLoader 等来准备应用程序上下文的运行环境。 - Launcher 类如何启动嵌入式服务器?
Launcher 类通过调用 getWebServer() 方法获取嵌入式服务器并将其启动。