SpringBoot系列(二) SpringBoot启动流程-关于Launcher类
org.springframework.boot.loader.Launcher
类是Spring Boot启动过程的入口点,也是Spring Boot的核心类之一。在Spring Boot应用程序启动时,Launcher
类的静态方法main()
将被执行,它主要负责设置Spring Boot运行环境和启动应用程序的主类。下面是对Launcher
类的详细解释。
构造函数
Launcher
类只有一个私有的构造函数:
private Launcher() {
}
这是一个私有构造函数,用于确保无法实例化Launcher
类。由于Launcher
类只有静态方法,因此该构造函数不会被调用。
main()方法
Launcher
类中所有的静态方法都是由main()
方法调用的。因此,main()
方法是Spring Boot应用程序启动流程的入口点。在main()
方法中,首先执行以下步骤:
- 创建
Logger
对象 - 打印Banner
- 设置SystemProperties
public static void main(String[] args) throws Exception {
...
PropertiesLauncher launcher = new PropertiesLauncher();
...
launcher.launch(args);
}
在以上步骤之后,main()
方法创建了一个PropertiesLauncher
对象,并执行了launch()
方法。PropertiesLauncher
是Spring Boot的默认启动器,并提供了一组必要的类和资源,以便Spring Boot应用程序可以被正确地启动和执行。
launch()方法
PropertiesLauncher
类的launch()
方法是应用程序启动过程的核心方法。它主要负责以下任务:
- 解析应用程序的Classpath
- 加载应用程序的JAR和CLASSPATH中的所有JAR
- 加载应用程序主类
- 创建
SpringApplication
对象 - 启动应用程序
private ClassLoader createClassLoader(
List<Archive> archives, ClassLoader parent) throws Exception {
...
return new LaunchedURLClassLoader(urls.toArray(new URL[0]), parent);
}
在PropertiesLauncher
类中,createClassLoader()
方法被用于创建一个LaunchedURLClassLoader
对象,这个ClassLoader可以从本地磁盘或网络下载的多个JAR文件中加载应用程序的类和资源。由于LaunchedURLClassLoader
是基于URL的ClassLoader,它可以从多个远程或本地位置加载类和资源。
加载应用程序的主类
PropertiesLauncher
类的另一个重要方法是load
方法,该方法负责查找并加载应用程序的主类。实际上,load()
方法是main()
方法中最重要的一部分,因为它确定了应用程序如何启动和运行。在Spring Boot应用程序中,主类通常是带有@SpringBootApplication
注解的类。
创建SpringApplication对象
在加载应用程序的主类之后,PropertiesLauncher
将使用主类名称创建一个SpringApplication
对象。这个对象是Spring Boot应用程序的入口点,并负责加载所有bean,处理成bean之间的依赖关系以及启动应用程序。
private SpringApplication createSpringApplication() {
SpringApplication application = new SpringApplication(this.mainClass);
return application;
}
这里,createSpringApplication()
方法负责创建Spring Boot应用程序的核心类SpringApplication
对象,并将主类传递给它。一旦SpringApplication
对象创建成功,就可以准备启动应用程序了。
启动应用程序
在创建了SpringApplication
对象之后,Spring Boot调用run()
方法启动应用程序。这个方法是非常复杂的,并包含了大量的代码,其中包括以下步骤:
- 获取SpringBoot的配置类(ApplicationClassList)并把它们添加到应用程序上下文中
- 应用程序上下文的Environment(环境)初始化
- 如果存在:
spring.main.sources
属性、或使用SpringApplication
的sources()
方法添加了源文件,则将这些类和资源添加到应用程序上下文中 - 对自定义的ApplicationContextInitializer进行调用。这些可以根据应用程序上下文进行配置,用于对ApplicationContext进行分析和修改,例如,添加propertySources或profiles等
- 如果存在:
spring.application.admin.enabled
属性的值为true,则创建一个SpringApplicationAdminMXBean实例,提供对Spring Boot应用程序的管理方法 - 创建并配置应用程序上下文
- 执行ApplicationContext的refresh()方法,完成应用程序上下文的初始化
- 对自定义的ApplicationRunner和CommandLineRunner进行执行。这些Runner是在ApplicationContext刷新之后开始执行的
- 向外部环境发布一个ApplicationStartedEvent通知,表示应用程序已启动
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
在run()
方法执行完成后,应用程序已启动并准备好接收客户端请求了。
在启动过程中,SpringApplication
对象扮演了非常重要的角色,它是Spring Boot应用程序的核心类之一。因此,了解SpringApplication
对象的创建和配置对于理解Spring Boot应用程序的启动过程至关重要。在使用Spring Boot时,在进行应用程序开发和维护时,我们应该始终牢记应用程序启动过程的核心原则,以避免一些常见问题并优化应用程序的性能。
结论
在本文中,我们对Spring Boot应用程序启动过程做了一个总体介绍,并深入了解了各个步骤的细节。了解Spring Boot启动流程是非常重要的,因为它可以使我们更好地理解应用程序的工作原理,并帮助我们在出现问题时更好地排除故障。通过对Spring Boot启动流程的阐明,我们可以更好地维护和优化自己的应用程序。
在本文中,我们了解了以下内容:
Launcher
类的作用和主要构造函数PropertiesLauncher
的作用和启动过程SpringApplication
对象的创建和配置- 应用程序的启动过程
感谢您阅读本文。如果您有任何疑问或反馈,请在下面的评论区留言。
转载自:https://juejin.cn/post/7242596419034890295